w11 - vhd 0.794
W11 CPU core and support modules
Loading...
Searching...
No Matches
c7_sram_memctl.vhd
Go to the documentation of this file.
1-- $Id: c7_sram_memctl.vhd 1181 2019-07-08 17:00:50Z mueller $
2-- SPDX-License-Identifier: GPL-3.0-or-later
3-- Copyright 2017- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4--
5------------------------------------------------------------------------------
6-- Module Name: c7_sram_memctl - syn
7-- Description: Cmod A7 SRAM controller
8--
9-- Dependencies: vlib/xlib/iob_reg_o
10-- vlib/xlib/iob_reg_o_gen
11-- vlib/xlib/iob_reg_io_gen
12--
13-- Test bench: tb/tb_c7_sram_memctl
14-- fw_gen/tst_sram/cmoda7/tb/tb_tst_sram_c7
15--
16-- Target Devices: generic
17-- Tool versions: viv 2017.1; ghdl 0.34
18--
19-- Synthesized (viv):
20-- Date Rev viv Target flop lutl lutm bram
21-- 2017-06-19 914 2017.1 xc7a35t-1 109 81 0 0 syn level
22--
23-- Revision History:
24-- Date Rev Version Comment
25-- 2017-07-01 920 1.0.1 shorten ce and oe times
26-- 2017-06-19 914 1.0 Initial version
27-- 2017-06-11 912 0.5 First draft
28--
29-- Timing of some signals:
30--
31-- single read request:
32--
33-- state |_idle |_read0 |_read1 |...._read0 |_read1 |_idle |
34--
35-- CLK __|^^^|___|^^^|___|^^^|___|....^^^|___|^^^|___|^^^|___|^^
36--
37-- REQ _________|^^^^^^^|____________________________________
38-- WE ______________________________________________________
39--
40-- IOB_CE __________|^^^^^^^^^^^^^^^^....^^^^^^^^^^^^^^^|_________
41-- IOB_OE __________|^^^^^^^^^^^^^^^^....^^^^^^^^^^^^^^^|_________
42--
43-- ADDR[1:0] | 00 | 00 |.... 11 | 11 |---------
44-- DATA ----------| data-0 | data-3 |---------
45-- BUSY __________|^^^^^^^^^^^^^^^^....^^^^^^^^^^^^^^^|________
46-- ACK_R ___________________________...._______|^^^^^^^|________
47--
48-- single write request (assume BE="0011")
49--
50-- state |_idle |_write0|_write1|_write0|_write1|_idle |
51--
52-- CLK __|^^^|___|^^^|___|^^^|___|^^^|___|^^^|___|^^^|___|^^
53--
54-- REQ _________|^^^^^^^|____________________________________
55-- WE _________|^^^^^^^|____________________________________
56--
57-- ADDR[1:0] | 00 | 00 |.... 01 | 01 |---------
58-- DATA ----------| data-0 |....data-1 |---------
59--
60-- IOB_CE __________|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|_________
61-- IOB_OE ________________________________________________________
62-- IOB_WE ______________|^^^^^^^|___________|^^^^^^^|_____________
63--
64-- BUSY __________|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|_________
65-- ACK_W ______________________________________|^^^^^^^|_________
66--
67------------------------------------------------------------------------------
68
69library ieee;
70use ieee.std_logic_1164.all;
71use ieee.numeric_std.all;
72
73use work.slvtypes.all;
74use work.xlib.all;
75
76entity c7_sram_memctl is -- SRAM controller for Cmod A7
77 port (
78 CLK : in slbit; -- clock
79 RESET : in slbit; -- reset
80 REQ : in slbit; -- request
81 WE : in slbit; -- write enable
82 BUSY : out slbit; -- controller busy
83 ACK_R : out slbit; -- acknowledge read
84 ACK_W : out slbit; -- acknowledge write
85 ACT_R : out slbit; -- signal active read
86 ACT_W : out slbit; -- signal active write
87 ADDR : in slv17; -- address
88 BE : in slv4; -- byte enable
89 DI : in slv32; -- data in (memory view)
90 DO : out slv32; -- data out (memory view)
91 O_MEM_CE_N : out slbit; -- sram: chip enable (act.low)
92 O_MEM_WE_N : out slbit; -- sram: write enable (act.low)
93 O_MEM_OE_N : out slbit; -- sram: output enable (act.low)
94 O_MEM_ADDR : out slv19; -- sram: address lines
95 IO_MEM_DATA : inout slv8 -- sram: data lines
96 );
98
99
100architecture syn of c7_sram_memctl is
101
102 type state_type is (
103 s_idle, -- s_idle: wait for req
104 s_read0, -- s_read0: read cycle, 1st half
105 s_read1, -- s_read1: read cycle, 2nd half
106 s_write0, -- s_write0: write cycle, 1st half
107 s_write1 -- s_write1: write cycle, 2nd half
108 );
109
110 type regs_type is record
111 state : state_type; -- state
112 addrb : slv2; -- byte address
113 be : slv4; -- be pending
114 memdi : slv32; -- MEM_DI buffer
115 memdo : slv24; -- MEM_DO buffer for byte 0,1,2
116 ackr : slbit; -- signal ack_r
117 end record regs_type;
118
119 constant regs_init : regs_type := (
120 s_idle, -- state
121 "00", -- addrb
122 "0000", -- be
123 (others=>'0'), -- memdi
124 (others=>'0'), -- memdo
125 '0' -- ackr
126 );
127
128 signal R_REGS : regs_type := regs_init; -- state registers
129 signal N_REGS : regs_type := regs_init; -- next value state regs
130
131 signal CLK_180 : slbit := '0';
132 signal MEM_CE_N : slbit := '0';
133 signal MEM_WE_N : slbit := '0';
134 signal MEM_OE_N : slbit := '0';
135 signal MEM_DI : slv8 := "00000000";
136 signal MEM_DO : slv8 := "00000000";
137 signal ADDRB : slv2 := "00";
138 signal ADDRW_CE : slbit := '0';
139 signal ADDRB_CE : slbit := '0';
140 signal DATA_CEI : slbit := '0';
141 signal DATA_CEO : slbit := '0';
142 signal DATA_OE : slbit := '0';
143
144begin
145
146 CLK_180 <= not CLK;
147
148 IOB_MEM_CE : iob_reg_o
149 generic map (
150 INIT => '1')
151 port map (
152 CLK => CLK,
153 CE => '1',
154 DO => MEM_CE_N,
155 PAD => O_MEM_CE_N
156 );
157
158 IOB_MEM_WE : iob_reg_o
159 generic map (
160 INIT => '1')
161 port map (
162 CLK => CLK_180,
163 CE => '1',
164 DO => MEM_WE_N,
165 PAD => O_MEM_WE_N
166 );
167
168 IOB_MEM_OE : iob_reg_o
169 generic map (
170 INIT => '1')
171 port map (
172 CLK => CLK,
173 CE => '1',
174 DO => MEM_OE_N,
175 PAD => O_MEM_OE_N
176 );
177
178 IOB_MEM_ADDRW : iob_reg_o_gen
179 generic map (
180 DWIDTH => 17)
181 port map (
182 CLK => CLK,
183 CE => ADDRW_CE,
184 DO => ADDR,
185 PAD => O_MEM_ADDR(18 downto 2)
186 );
187
188 IOB_MEM_ADDRB : iob_reg_o_gen
189 generic map (
190 DWIDTH => 2)
191 port map (
192 CLK => CLK,
193 CE => ADDRB_CE,
194 DO => ADDRB,
195 PAD => O_MEM_ADDR(1 downto 0)
196 );
197
198 IOB_MEM_DATA : iob_reg_io_gen
199 generic map (
200 DWIDTH => 8,
201 PULL => "NONE")
202 port map (
203 CLK => CLK,
204 CEI => DATA_CEI,
205 CEO => DATA_CEO,
206 OE => DATA_OE,
207 DI => MEM_DO,
208 DO => MEM_DI,
210 );
211
212 proc_regs: process (CLK)
213 begin
214
215 if rising_edge(CLK) then
216 if RESET = '1' then
217 R_REGS <= regs_init;
218 else
219 R_REGS <= N_REGS;
220 end if;
221 end if;
222
223 end process proc_regs;
224
225 proc_next: process (R_REGS, REQ, WE, BE, MEM_DO, DI)
226
227 variable r : regs_type := regs_init;
228 variable n : regs_type := regs_init;
229 variable ibusy : slbit := '0';
230 variable iackw : slbit := '0';
231 variable iactr : slbit := '0';
232 variable iactw : slbit := '0';
233 variable imem_ce : slbit := '0';
234 variable imem_we : slbit := '0';
235 variable imem_oe : slbit := '0';
236 variable iaddrw_ce : slbit := '0';
237 variable iaddrb : slv2 := "00";
238 variable iaddrb_be : slv2 := "00";
239 variable iaddrb_ce : slbit := '0';
240 variable idata_cei : slbit := '0';
241 variable idata_ceo : slbit := '0';
242 variable idata_oe : slbit := '0';
243 variable imem_di : slv8 := "00000000";
244
245 begin
246
247 r := R_REGS;
248 n := R_REGS;
249 n.ackr := '0';
250
251 ibusy := '0';
252 iackw := '0';
253 iactr := '0';
254 iactw := '0';
255
256 imem_ce := '0';
257 imem_we := '0';
258 imem_oe := '0';
259 iaddrw_ce := '0';
260 iaddrb := "00";
261 iaddrb_be := "00";
262 iaddrb_ce := '0';
263 idata_cei := '0';
264 idata_ceo := '0';
265 idata_oe := '0';
266
267 imem_di := "00000000";
268 if r.be(0) = '1' then
269 iaddrb_be := "00";
270 imem_di := r.memdi( 7 downto 0);
271 elsif r.be(1) = '1' then
272 iaddrb_be := "01";
273 imem_di := r.memdi(15 downto 8);
274 elsif r.be(2) = '1' then
275 iaddrb_be := "10";
276 imem_di := r.memdi(23 downto 16);
277 elsif r.be(3) = '1' then
278 iaddrb_be := "11";
279 imem_di := r.memdi(31 downto 24);
280 end if;
281
282 case r.state is
283 when s_idle => -- s_idle: wait for req
284 if REQ = '1' then -- if IO requested
285 if WE = '0' then -- if READ requested
286 iaddrw_ce := '1'; -- latch word address
287 iaddrb_ce := '1'; -- latch byte address (use 0)
288 imem_ce := '1'; -- ce SRAM next cycle
289 imem_oe := '1'; -- oe SRAM next cycle
290 n.state := s_read0; -- next: read0
291 else -- if WRITE requested
292 iaddrw_ce := '1'; -- latch word address
293 n.be := BE; -- latch pending BEs
294 n.memdi := DI; -- latch data
295 n.state := s_write1; -- next: write 2nd part
296 end if;
297 end if;
298
299 when s_read0 => -- s_read0: read cycle, 1st half
300 ibusy := '1'; -- signal busy, unable to handle req
301 iactr := '1'; -- signal mem read
302 imem_ce := '1'; -- ce SRAM next cycle
303 imem_oe := '1'; -- oe SRAM next cycle
304 case r.addrb is -- capture last byte; inc byte count
305 when "00" => n.addrb := "01";
306 when "01" => n.addrb := "10"; n.memdo( 7 downto 0) := MEM_DO;
307 when "10" => n.addrb := "11"; n.memdo(15 downto 8) := MEM_DO;
308 when "11" => n.addrb := "00"; n.memdo(23 downto 16) := MEM_DO;
309 when others => null;
310 end case;
311 n.state := s_read1; -- next: read1
312
313 when s_read1 => -- s_read1: read cycle, 2nd half
314 ibusy := '1'; -- signal busy, unable to handle req
315 iactr := '1'; -- signal mem read
316 idata_cei := '1'; -- latch input data
317 if r.addrb = "00" then -- last byte seen (counter wrapped) ?
318 n.ackr := '1'; -- ACK_R next cycle
319 n.state := s_idle;
320 else -- more bytes to do ?
321 imem_ce := '1'; -- ce SRAM next cycle
322 imem_oe := '1'; -- oe SRAM next cycle
323 iaddrb := r.addrb; -- use addrb counter
324 iaddrb_ce := '1'; -- latch byte address (use r.addrb)
325 n.state := s_read0;
326 end if;
327
328 when s_write0 => -- s_write0: write cycle, 1st half
329 ibusy := '1'; -- signal busy, unable to handle req
330 iactw := '1'; -- signal mem write
331 idata_oe := '1'; -- oe FPGA next cycle
332 imem_ce := '1'; -- ce SRAM next cycle
333 imem_we := '1'; -- we SRAM next shifted cycle
334 n.state := s_write1; -- next: write cycle, 2nd half
335
336 when s_write1 => -- s_write1: write cycle, 2nd half
337 ibusy := '1'; -- signal busy, unable to handle req
338 iactw := '1'; -- signal mem write
339 if r.be = "0000" then -- all done ?
340 iackw := '1'; -- signal write acknowledge
341 n.state := s_idle; -- next: idle
342 else -- more to do ?
343 idata_oe := '1'; -- oe FPGA next cycle
344 imem_ce := '1'; -- ce SRAM next cycle
345 idata_ceo := '1'; -- latch output data (to SRAM)
346 iaddrb := iaddrb_be; -- use addrb from be encode
347 iaddrb_ce := '1'; -- latch byte address (use iaddr_be)
348 n.be(to_integer(unsigned(iaddrb_be))) := '0'; -- mark byte done
349 n.state := s_write0; -- next: write 1st half
350 end if;
351
352 when others => null;
353 end case;
354
355 N_REGS <= n;
356
357 MEM_CE_N <= not imem_ce;
358 MEM_WE_N <= not imem_we;
359 MEM_OE_N <= not imem_oe;
360 MEM_DI <= imem_di;
361 ADDRW_CE <= iaddrw_ce;
362 ADDRB <= iaddrb;
363 ADDRB_CE <= iaddrb_ce;
364 DATA_CEI <= idata_cei;
365 DATA_CEO <= idata_ceo;
366 DATA_OE <= idata_oe;
367
368 BUSY <= ibusy;
369 ACK_R <= r.ackr;
370 ACK_W <= iackw;
371 ACT_R <= iactr;
372 ACT_W <= iactw;
373 DO <= MEM_DO & r.memdo;
374
375 end process proc_next;
376
377end syn;
slv8 := "00000000" MEM_DI
regs_type :=( s_idle, "00", "0000",( others => '0'),( others => '0'), '0') regs_init
slv8 := "00000000" MEM_DO
slbit := '0' ADDRB_CE
slbit := '0' CLK_180
regs_type := regs_init N_REGS
slbit := '0' MEM_OE_N
slbit := '0' DATA_OE
regs_type := regs_init R_REGS
slbit := '0' DATA_CEO
(s_idle,s_read0,s_read1,s_write0,s_write1) state_type
slbit := '0' ADDRW_CE
slbit := '0' MEM_WE_N
slbit := '0' MEM_CE_N
slbit := '0' DATA_CEI
out ACT_W slbit
out O_MEM_WE_N slbit
inout IO_MEM_DATA slv8
out ACK_R slbit
out BUSY slbit
out O_MEM_CE_N slbit
out ACT_R slbit
out ACK_W slbit
out O_MEM_OE_N slbit
out O_MEM_ADDR slv19
in CEO slbit := '1'
in CEI slbit := '1'
PULL string := "NONE"
inout PAD slv( DWIDTH- 1 downto 0)
in DO slv( DWIDTH- 1 downto 0)
out DI slv( DWIDTH- 1 downto 0)
DWIDTH positive := 16
in CE slbit := '1'
out PAD slv( DWIDTH- 1 downto 0)
in CLK slbit
in DO slv( DWIDTH- 1 downto 0)
DWIDTH positive := 16
in CE slbit := '1'
Definition: iob_reg_o.vhd:30
out PAD slbit
Definition: iob_reg_o.vhd:33
INIT slbit := '0'
Definition: iob_reg_o.vhd:27
in CLK slbit
Definition: iob_reg_o.vhd:29
in DO slbit
Definition: iob_reg_o.vhd:31
std_logic_vector( 18 downto 0) slv19
Definition: slvtypes.vhd:52
std_logic_vector( 3 downto 0) slv4
Definition: slvtypes.vhd:36
std_logic_vector( 16 downto 0) slv17
Definition: slvtypes.vhd:50
std_logic_vector( 31 downto 0) slv32
Definition: slvtypes.vhd:59
std_logic slbit
Definition: slvtypes.vhd:30
std_logic_vector( 7 downto 0) slv8
Definition: slvtypes.vhd:40
std_logic_vector( 23 downto 0) slv24
Definition: slvtypes.vhd:57
std_logic_vector( 1 downto 0) slv2
Definition: slvtypes.vhd:34
Definition: xlib.vhd:35