2 * Copyright 2018 Jacob Lifshay
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:
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
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
24 module cpu_memory_interface(
27 input [31:2] fetch_address,
28 output [31:0] fetch_data,
30 input [31:2] rw_address,
31 input [3:0] rw_byte_mask,
32 input rw_read_not_write,
34 input [31:0] rw_data_in,
35 output [31:0] rw_data_out,
36 output rw_address_valid,
39 output reg [7:0] tty_write_data,
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;
52 wire ram_a_write_enable = ~reset & ~ignore_after_delay & rw_active & rw_address_in_mem_space & ~rw_read_not_write;
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;
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)
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;
80 assign fetch_data = ram_b_read_output;
82 assign fetch_valid = ~reset & fetch_address_valid;
84 assign rw_wait = (rw_address_in_mem_space
88 : ~delay_done) | reset;
90 reg ignore_after_delay = 0;
92 reg [31:0] io_read_output_register;
93 reg last_read_was_ram;
95 assign rw_data_out = last_read_was_ram ? ram_a_read_output : io_read_output_register;
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];
105 always @(posedge clk or posedge reset) begin
109 ignore_after_delay <= 0;
110 io_read_output_register <= 'hXXXXXXXX;
111 last_read_was_ram <= 1'hX;
117 if(ignore_after_delay) begin
118 ignore_after_delay <= 0;
120 else if(rw_active & rw_address_in_mem_space) begin
121 if(rw_read_not_write) begin
123 ignore_after_delay <= 1;
124 last_read_was_ram <= 1;
127 last_read_was_ram <= 1;
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;
136 ignore_after_delay <= 1;
139 if(tty_write_busy) begin
144 tty_write_data <= rw_data_in[7:0];
146 ignore_after_delay <= 1;
148 last_read_was_ram <= 0;
149 io_read_output_register <= 'hXXXXXXXX;
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};
157 ignore_after_delay <= 1;
161 gpio_output <= rw_data_in[7:0];
163 ignore_after_delay <= 1;
164 last_read_was_ram <= 0;
165 io_read_output_register <= 'hXXXXXXXX;
169 //TODO finish implementing I/O
170 last_read_was_ram <= 0;
171 io_read_output_register <= 'hXXXXXXXX;
175 last_read_was_ram <= 0;
176 io_read_output_register <= 'hXXXXXXXX;