summaryrefslogtreecommitdiff
path: root/hdl/ram_controller.sv
diff options
context:
space:
mode:
Diffstat (limited to 'hdl/ram_controller.sv')
-rw-r--r--hdl/ram_controller.sv193
1 files changed, 193 insertions, 0 deletions
diff --git a/hdl/ram_controller.sv b/hdl/ram_controller.sv
new file mode 100644
index 0000000..b6e744b
--- /dev/null
+++ b/hdl/ram_controller.sv
@@ -0,0 +1,193 @@
1module ram_controller
2 ( input bit clock
3 , input bit resetn
4
5 , output bit command_ready
6 , input bit command_valid
7 , input bit [23:0] command_address
8 , input bit command_write
9 , input bit [15:0] command_data
10
11 , input bit result_ready
12 , output bit result_valid
13 , output bit [15:0] result_data
14
15 , output bit ram_resetn
16 , output bit [1:0] ram_csn
17 , output bit ram_clkp
18 , output bit ram_clkn
19 , output bit ram_rwds_oe
20 , input bit ram_rwds_in
21 , output bit ram_rwds_out
22 , output bit ram_data_oe
23 , input bit [7:0] ram_data_in
24 , output bit [7:0] ram_data_out
25 );
26
27 assign ram_clkn = !ram_clkp;
28
29 bit valid;
30 bit [23:0] address;
31 bit write;
32 bit [15:0] data;
33
34 bit slow;
35
36 enum
37 { SEND_COMMAND_1
38 , SEND_COMMAND_2
39 , SEND_COMMAND_3
40 , SEND_COMMAND_4
41 , SEND_COMMAND_5
42 , SEND_COMMAND_6
43
44 , LAT2_CYC1
45 , LAT2_CYC2
46 , LAT2_CYC3
47 , LAT2_CYC4
48 , LAT2_CYC5
49 , LAT2_CYC6
50
51 , LAT1_CYC1
52 , LAT1_CYC2
53 , LAT1_CYC3
54 , LAT1_CYC4
55 // Latency blocks are 6 cycle, but they start in the SEND_COMMAND_5 cycle, so block 1 is only 4 real cycles
56 //, LAT1_CYC5
57 //, LAT1_CYC6
58
59 , DATA_1
60 , DATA_2
61 } state;
62
63 int reset_counter;
64
65 always @(posedge clock) begin
66 if (!resetn || reset_counter != 0) begin
67 command_ready = 0;
68 result_valid = 0;
69 result_data = 0;
70 ram_resetn = 0;
71 ram_csn[0] = 1;
72 ram_csn[1] = 1;
73 ram_clkp = 0;
74 ram_rwds_oe = 0;
75 ram_rwds_out = 0;
76 ram_data_oe = 0;
77 ram_data_out = 0;
78 valid = 0;
79 address = 0;
80 write = 0;
81 data = 0;
82 slow = 0;
83 state = state.first;
84 if (!resetn)
85 reset_counter = 5; // Spec wants >= 100ns of reset
86 else
87 reset_counter = reset_counter - 1;
88 end else begin
89 ram_resetn = 1;
90 ram_rwds_oe = 0;
91 ram_data_oe = 0;
92
93 if (result_ready) result_valid = 0;
94 if (command_ready && command_valid) begin
95 valid = 1;
96 address = command_address;
97 write = command_write;
98 data = command_data;
99 state = state.first;
100 end
101
102 if (!valid) begin
103 ram_csn[0] = 1;
104 ram_csn[1] = 1;
105 ram_clkp = 0;
106 end else begin
107 case (state)
108
109 SEND_COMMAND_1: begin
110 ram_clkp = 0;
111 ram_csn[address[23]] = 0;
112 ram_data_oe = 1;
113 ram_data_out = {!write, 1'b0, 1'b0, 5'b0}; // R/W# AS BURST RESERVED
114 state = state.next;
115 end
116
117 SEND_COMMAND_2: begin
118 ram_clkp = 1;
119 ram_data_oe = 1;
120 ram_data_out = {4'b0, address[22:19]}; // RESERVED ROW
121 state = state.next;
122 end
123
124 SEND_COMMAND_3: begin
125 ram_clkp = 0;
126 ram_data_oe = 1;
127 ram_data_out = {address[18:11]}; // ROW
128 state = state.next;
129 end
130
131 SEND_COMMAND_4: begin
132 ram_clkp = 1;
133 ram_data_oe = 1;
134 ram_data_out = {address[10:9], address[8:3]}; // ROW UPPERCOL
135 slow = ram_rwds_in; // Sort of arbitrarily capturing RWDS in the middle of the command string
136 state = state.next;
137 end
138
139 SEND_COMMAND_5: begin
140 ram_clkp = 0;
141 ram_data_oe = 1;
142 ram_data_out = {8'b0}; // RESERVED
143 state = state.next;
144 end
145
146 SEND_COMMAND_6: begin
147 ram_clkp = 1;
148 ram_data_oe = 1;
149 ram_data_out = {5'b0, address[2:0]}; // RESERVED LOWERCOL
150 if (slow)
151 state = LAT2_CYC1;
152 else
153 state = LAT1_CYC1;
154 end
155
156 LAT2_CYC1, LAT2_CYC2, LAT2_CYC3, LAT2_CYC4, LAT2_CYC5, LAT2_CYC6,
157 LAT1_CYC1, LAT1_CYC2, LAT1_CYC3, LAT1_CYC4: begin
158 ram_clkp = !ram_clkp;
159 state = state.next;
160 end
161
162 DATA_1, DATA_2: begin
163 ram_clkp = !ram_clkp;
164 if (write) begin
165 ram_rwds_oe = 1;
166 ram_rwds_out = 1;
167 ram_data_oe = 1;
168 ram_data_out = data[7:0];
169 data = data >> 8;
170 state = state.next;
171 end else if (ram_rwds_in) begin
172 data = data << 8;
173 data[7:0] = ram_data_in;
174 state = state.next;
175 end
176 end
177
178 endcase
179 if (state == state.first) begin
180 valid = 0;
181 if (!write) begin
182 // We know that this is safe because we don't accept commands unless we have result bandwidth
183 result_valid = 1;
184 result_data = data;
185 end
186 end
187 end
188
189 command_ready = !valid && !result_valid;
190 end
191 end
192
193endmodule