more cpu decode conversion
[rv32.git] / cpu_memory_interface.v
1 /*
2 * Copyright 2018 Jacob Lifshay
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 *
22 */
23 `timescale 1ns / 1ps
24 module cpu_memory_interface(
25 input clk,
26 input reset,
27 input [31:2] fetch_address,
28 output [31:0] fetch_data,
29 output fetch_valid,
30 input [31:2] rw_address,
31 input [3:0] rw_byte_mask,
32 input rw_read_not_write,
33 input rw_active,
34 input [31:0] rw_data_in,
35 output [31:0] rw_data_out,
36 output rw_address_valid,
37 output rw_wait,
38 output reg tty_write,
39 output reg [7:0] tty_write_data,
40 input tty_write_busy,
41 input switch_2,
42 input switch_3,
43 output led_1,
44 output led_3
45 );
46
47 parameter ram_size = 32'hXXXXXXXX;
48 parameter ram_start = 32'hXXXXXXXX;
49 parameter tty_location = 32'h8000_0000;
50 parameter gpio_location = 32'h8000_0010;
51
52 wire ram_a_write_enable = ~reset & ~ignore_after_delay & rw_active & rw_address_in_mem_space & ~rw_read_not_write;
53
54 wire [31:0] ram_a_ram_address = rw_address_in_mem_space ? rw_address - ram_start / 4 : 0;
55 wire [3:0] ram_a_write_enable_bytes = {4{ram_a_write_enable}} & rw_byte_mask;
56 wire [31:0] ram_a_write_input = rw_data_in;
57 wire [31:0] ram_a_read_output;
58 wire [31:0] ram_b_ram_address = fetch_address_valid ? fetch_address - ram_start / 4 : 0;
59 wire [31:0] ram_b_read_output;
60
61 block_memory ram(
62 .clk(clk),
63 .a_ram_address(ram_a_ram_address),
64 .a_write_enable(ram_a_write_enable_bytes),
65 .a_write_input(ram_a_write_input),
66 .a_read_output(ram_a_read_output),
67 .b_ram_address(ram_b_ram_address),
68 .b_read_output(ram_b_read_output)
69 );
70
71 wire fetch_address_valid = (fetch_address >= ram_start / 4) & (fetch_address < (ram_start + ram_size) / 4);
72 wire rw_address_is_tty = (rw_address == tty_location / 4) & (rw_read_not_write | rw_byte_mask == 4'h1);
73 wire rw_address_is_gpio = rw_address == gpio_location / 4;
74 wire rw_address_in_io_space = rw_address_is_tty | rw_address_is_gpio;
75 wire rw_address_in_mem_space = (rw_address >= ram_start / 4) & (rw_address < (ram_start + ram_size) / 4);
76 assign rw_address_valid = rw_address_in_mem_space | rw_address_in_io_space;
77
78 reg delay_done = 0;
79
80 assign fetch_data = ram_b_read_output;
81
82 assign fetch_valid = ~reset & fetch_address_valid;
83
84 assign rw_wait = (rw_address_in_mem_space
85 ? (rw_read_not_write
86 ? ~delay_done
87 : 1'b0)
88 : ~delay_done) | reset;
89
90 reg ignore_after_delay = 0;
91
92 reg [31:0] io_read_output_register;
93 reg last_read_was_ram;
94
95 assign rw_data_out = last_read_was_ram ? ram_a_read_output : io_read_output_register;
96
97 reg [7:0] gpio_input_sync_first = 0;
98 reg [7:0] gpio_input = 0;
99 always @(posedge clk) gpio_input_sync_first <= {5'b0, ~switch_3, ~switch_2, 1'b0};
100 always @(posedge clk) gpio_input <= gpio_input_sync_first;
101 reg [7:0] gpio_output = 0;
102 assign led_1 = ~gpio_output[0];
103 assign led_3 = ~gpio_output[2];
104
105 always @(posedge clk or posedge reset) begin
106 if(reset) begin
107 delay_done <= 0;
108 tty_write <= 0;
109 ignore_after_delay <= 0;
110 io_read_output_register <= 'hXXXXXXXX;
111 last_read_was_ram <= 1'hX;
112 gpio_output <= 0;
113 end
114 else begin
115 delay_done <= 0;
116 tty_write <= 0;
117 if(ignore_after_delay) begin
118 ignore_after_delay <= 0;
119 end
120 else if(rw_active & rw_address_in_mem_space) begin
121 if(rw_read_not_write) begin
122 delay_done <= 1;
123 ignore_after_delay <= 1;
124 last_read_was_ram <= 1;
125 end
126 else begin
127 last_read_was_ram <= 1;
128 end
129 end
130 else if(rw_active & rw_address_in_io_space) begin
131 if(rw_address_is_tty) begin
132 if(rw_read_not_write) begin
133 last_read_was_ram <= 0;
134 io_read_output_register <= 0;
135 delay_done <= 1;
136 ignore_after_delay <= 1;
137 end
138 else begin
139 if(tty_write_busy) begin
140 delay_done <= 0;
141 end
142 else begin
143 tty_write <= 1;
144 tty_write_data <= rw_data_in[7:0];
145 delay_done <= 1;
146 ignore_after_delay <= 1;
147 end
148 last_read_was_ram <= 0;
149 io_read_output_register <= 'hXXXXXXXX;
150 end
151 end
152 else if(rw_address_is_gpio) begin
153 if(rw_read_not_write) begin
154 last_read_was_ram <= 0;
155 io_read_output_register <= {16'b0, gpio_input, gpio_output};
156 delay_done <= 1;
157 ignore_after_delay <= 1;
158 end
159 else begin
160 if(rw_byte_mask[0])
161 gpio_output <= rw_data_in[7:0];
162 delay_done <= 1;
163 ignore_after_delay <= 1;
164 last_read_was_ram <= 0;
165 io_read_output_register <= 'hXXXXXXXX;
166 end
167 end
168 else begin
169 //TODO finish implementing I/O
170 last_read_was_ram <= 0;
171 io_read_output_register <= 'hXXXXXXXX;
172 end
173 end
174 else begin
175 last_read_was_ram <= 0;
176 io_read_output_register <= 'hXXXXXXXX;
177 end
178 end
179 end
180
181 endmodule