w11 - vhd 0.794
W11 CPU core and support modules
Loading...
Searching...
No Matches
sramif2migui_core.vhd
Go to the documentation of this file.
1-- $Id: sramif2migui_core.vhd 1181 2019-07-08 17:00:50Z mueller $
2-- SPDX-License-Identifier: GPL-3.0-or-later
3-- Copyright 2018- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4--
5------------------------------------------------------------------------------
6-- Module Name: sramif2migui_core - syn
7-- Description: SRAM to MIG interface core
8--
9-- Dependencies: memlib/fifo_2c_dram2
10-- cdclib/cdc_signal_s1
11-- Test bench: tb/tb_sramif2migui_core
12-- Target Devices: generic
13-- Tool versions: viv 2017.2; ghdl 0.34
14--
15-- Revision History:
16-- Date Rev Version Comment
17-- 2018-12-28 1096 1.0 Initial version
18-- 2018-11-04 1066 0.1 First draft
19--
20------------------------------------------------------------------------------
21
22library ieee;
23use ieee.std_logic_1164.all;
24use ieee.numeric_std.all;
25
26use work.slvtypes.all;
27use work.memlib.all;
28use work.cdclib.all;
29use work.miglib.all;
30
31entity sramif2migui_core is -- SRAM to MIG interface core
32 generic (
33 BAWIDTH : positive := 4; -- byte address width
34 MAWIDTH : positive := 28); -- memory address width
35 port (
36 CLK : in slbit; -- clock
37 RESET : in slbit; -- reset
38 REQ : in slbit; -- request
39 WE : in slbit; -- write enable
40 BUSY : out slbit; -- controller busy
41 ACK_R : out slbit; -- acknowledge read
42 ACK_W : out slbit; -- acknowledge write
43 ACT_R : out slbit; -- signal active read
44 ACT_W : out slbit; -- signal active write
45 ADDR : in slv20; -- address (32 bit word address)
46 BE : in slv4; -- byte enable
47 DI : in slv32; -- data in (memory view)
48 DO : out slv32; -- data out (memory view)
49 MONI : out sramif2migui_moni_type; -- monitor signals
50 UI_CLK : in slbit; -- MIGUI clock
51 UI_CLK_SYNC_RST : in slbit; -- MIGUI reset
52 INIT_CALIB_COMPLETE : in slbit; -- MIGUI calibration done
53 APP_RDY : in slbit; -- MIGUI ready for cmd
54 APP_EN : out slbit; -- MIGUI command enable
55 APP_CMD : out slv3; -- MIGUI command
56 APP_ADDR : out slv(MAWIDTH-1 downto 0); -- MIGUI address
57 APP_WDF_RDY : in slbit; -- MIGUI ready for data write
58 APP_WDF_WREN : out slbit; -- MIGUI data write enable
59 APP_WDF_DATA : out slv(8*(2**BAWIDTH)-1 downto 0);-- MIGUI write data
60 APP_WDF_MASK : out slv((2**BAWIDTH)-1 downto 0); -- MIGUI write mask
61 APP_WDF_END : out slbit; -- MIGUI write end
62 APP_RD_DATA_VALID : in slbit; -- MIGUI read valid
63 APP_RD_DATA : in slv(8*(2**BAWIDTH)-1 downto 0);-- MIGUI read data
64 APP_RD_DATA_END : in slbit -- MIGUI read end
65 );
67
68
69architecture syn of sramif2migui_core is
70
71 constant mwidth : positive := 2**BAWIDTH; -- mask width (8 or 16)
72 constant dwidth : positive := 8*mwidth; -- data width (64 or 128)
73 constant tawidth : positive := 20-(BAWIDTH-2); -- tag address width
74 constant rfwidth : positive := dwidth+mwidth+tawidth+1; -- req fifo width
75
76 -- sram address fields
77 subtype sa_f_ta is integer range 20-1 downto BAWIDTH-2; -- tag addr
78 subtype sa_f_ga is integer range BAWIDTH-3 downto 0; -- group addr
79 -- mig address fields
80 subtype ma_f_ta is integer range 22-1 downto BAWIDTH; -- tag addr
81
82 -- request fifo data fields
83 subtype rf_f_data is integer range dwidth+mwidth+tawidth
84 downto MWIDTH+tawidth+1;
85 subtype rf_f_mask is integer range mwidth+tawidth downto tawidth+1;
86 subtype rf_f_addr is integer range tawidth downto 1;
87 constant rf_f_we : integer := 0;
88
89 constant ngrp : positive := 2**(BAWIDTH-2); -- # of 32bit groups (2 or 4)
90
91 type regs_type is record
92 actr : slbit; -- active read flag
93 actw : slbit; -- active write flag
94 ackr : slbit; -- read acknowledge
95 req_addr : slv20; -- request address
96 req_be : slv4; -- request be
97 req_di : slv32; -- request di
98 res_do : slv32; -- response do
99 rdbuf : slv(dwidth-1 downto 0); -- read buffer
100 rdtag : slv(tawidth-1 downto 0); -- read tag address
101 rdval : slbit; -- read buffer valid
102 rdnew : slbit; -- read buffer new
103 rdpend : slbit; -- read request pending
104 wrbuf : slv(dwidth-1 downto 0); -- write buffer
105 wrtag : slv(tawidth-1 downto 0); -- write tag address
106 wrpend : slv(mwidth-1 downto 0); -- write buffer pending flags
107 end record regs_type;
108
109 constant bufzero : slv(dwidth-1 downto 0) := (others=>'0');
110 constant tagzero : slv(tawidth-1 downto 0) := (others=>'0');
111 constant pendzero : slv(mwidth-1 downto 0) := (others=>'0');
112
113 constant regs_init : regs_type := (
114 '0','0','0', -- actr,actw,ackr
115 (others=>'0'), -- req_addr
116 (others=>'0'), -- req_be
117 (others=>'0'), -- req_di
118 (others=>'0'), -- res_do
119 bufzero, -- rdbuf
120 tagzero, -- rdtag
121 '0','0','0', -- rdval,rdnew,rdpend
122 bufzero, -- wrbuf
123 tagzero, -- wrtag
124 pendzero -- wrpend
125 );
126
128 signal N_REGS : regs_type; -- don't init (vivado fix for fsm infer)
129
130 signal REQ_DI : slv(rfwidth-1 downto 0) := (others=>'0');
131 signal REQ_DO : slv(rfwidth-1 downto 0) := (others=>'0');
132 signal REQ_ENA : slbit := '0';
133 signal REQ_VAL : slbit := '0';
134 signal REQ_HOLD : slbit := '0';
135 signal REQ_SIZE : slv4 := (others=>'0');
136
137 signal RES_DI : slv(dwidth-1 downto 0) := (others=>'0');
138 signal RES_DO : slv(dwidth-1 downto 0) := (others=>'0');
139 signal RES_ENA : slbit := '0';
140 signal RES_VAL : slbit := '0';
141
142 signal APP_RDY_CLK : slbit := '0'; -- APP_RDY sync'ed to CLK
143 signal APP_WDF_RDY_CLK : slbit := '0'; -- APP_WDF_RDY_CLK sync'ed to CLK
144 signal MIGUIRST_CLK : slbit := '0'; -- UI_CLK_SYNC_RST sync'ed to CLK
145 signal MIGCACO_CLK : slbit := '0'; -- INIT_CALIB_COMPLETE sync'ed to CLK
146
147begin
148
149 assert BAWIDTH = 3 or BAWIDTH = 4
150 report "assert( BAWIDTH = 3 or 4 )"
151 severity failure;
152
153 REQFIFO : fifo_2c_dram2 -- request fifo
154 generic map (
155 AWIDTH => 4,
156 DWIDTH => rfwidth)
157 port map (
158 CLKW => CLK,
159 CLKR => UI_CLK,
160 RESETW => '0',
161 RESETR => '0',
162 DI => REQ_DI,
163 ENA => REQ_ENA,
164 BUSY => open,
165 DO => REQ_DO,
166 VAL => REQ_VAL,
167 HOLD => REQ_HOLD,
168 SIZEW => REQ_SIZE,
169 SIZER => open
170 );
171
172 RESFIFO : fifo_2c_dram2 -- response fifo
173 generic map (
174 AWIDTH => 4,
175 DWIDTH => dwidth)
176 port map (
177 CLKW => UI_CLK,
178 CLKR => CLK,
179 RESETW => '0',
180 RESETR => '0',
181 DI => RES_DI,
182 ENA => RES_ENA,
183 BUSY => open,
184 DO => RES_DO,
185 VAL => RES_VAL,
186 HOLD => '0',
187 SIZEW => open,
188 SIZER => open
189 );
190
191 -- cdc for monitoring sigals from UI_CLK to CLK
192 CDC_CRDY : cdc_signal_s1
193 port map (
194 CLKO => CLK,
195 DI => APP_RDY,
196 DO => APP_RDY_CLK
197 );
198 CDC_WRDY : cdc_signal_s1
199 port map (
200 CLKO => CLK,
201 DI => APP_WDF_RDY,
203 );
204 CDC_UIRST : cdc_signal_s1
205 port map (
206 CLKO => CLK,
209 );
210 CDC_CACO : cdc_signal_s1
211 port map (
212 CLKO => CLK,
214 DO => MIGCACO_CLK
215 );
216
217 proc_regs: process (CLK)
218 begin
219
220 if rising_edge(CLK) then
221 if RESET = '1' then
222 R_REGS <= regs_init;
223 else
224 R_REGS <= N_REGS;
225 end if;
226 end if;
227
228 end process proc_regs;
229
230 proc_next: process (R_REGS, REQ, ADDR, BE, DI, WE,
233
234 variable r : regs_type := regs_init;
235 variable n : regs_type := regs_init;
236
237 variable iga : integer := 0;
238 variable ireqena : slbit := '0';
239 variable iackw : slbit := '0';
240 variable imoni : sramif2migui_moni_type := sramif2migui_moni_init;
241
242 variable iwrbuf : slv(dwidth-1 downto 0) := (others=>'0');
243 variable ireqdi : slv(rfwidth-1 downto 0) := (others=>'0');
244
245 begin
246
247 r := R_REGS;
248 n := R_REGS;
249
250 iga := 0;
251 ireqena := '0';
252 iackw := '0';
253 imoni := sramif2migui_moni_init;
254
255 imoni.migcbusy := not APP_RDY_CLK;
256 imoni.migwbusy := not APP_WDF_RDY_CLK;
257 imoni.miguirst := MIGUIRST_CLK;
258 imoni.migcacow := not MIGCACO_CLK;
259
260 -- setup request fifo data for write (the default)
261 ireqdi(rf_f_data) := r.wrbuf;
262 ireqdi(rf_f_mask) := not r.wrpend; -- -- MASK = not WE !!
263 ireqdi(rf_f_addr) := r.wrtag;
264 ireqdi(rf_f_we) := '1';
265
266 n.ackr := '0'; -- ensure one-shot
267
268 -- handle idle state, capture input, and activate read or write
269 if r.actr='0' and r.actw='0' then
270 if REQ = '1' then
271 n.req_addr := ADDR;
272 n.req_be := BE;
273 n.req_di := DI;
274 if WE = '1' then -- write request
275 n.actw := '1';
276 if r.wrtag = ADDR(sa_f_ta) then -- row hit
277 imoni.wrrhit := '1';
278 else -- row miss
279 if r.wrpend /= pendzero then -- if write buffer pending
280 ireqena := '1'; -- queue write request
281 n.wrpend := pendzero; -- clear pending flags
282 imoni.wrflush := '1';
283 end if;
284 end if;
285
286 else -- read request
287 n.actr := '1';
288 end if; -- WE='1'
289
290 end if; -- REQ='1'
291 end if;
292
293 iga := to_integer(unsigned(r.req_addr(sa_f_ga))); -- current group index
294
295 -- handle write request
296 if r.actw = '1' then
297 -- write into wrbuf and wrpend, no pending data left when here
298 if r.req_be(0) = '1' then
299 n.wrbuf(32*iga+ 7 downto 32*iga ) := r.req_di( 7 downto 0);
300 end if;
301 if r.req_be(1) = '1' then
302 n.wrbuf(32*iga+15 downto 32*iga+ 8) := r.req_di(15 downto 8);
303 end if;
304 if r.req_be(2) = '1' then
305 n.wrbuf(32*iga+23 downto 32*iga+16) := r.req_di(23 downto 16);
306 end if;
307 if r.req_be(3) ='1' then
308 n.wrbuf(32*iga+31 downto 32*iga+24) := r.req_di(31 downto 24);
309 end if;
310
311 n.wrtag := r.req_addr(sa_f_ta); -- set new tag address
312 n.wrpend(4*iga+3 downto 4*iga) := -- and update pending flags
313 n.wrpend(4*iga+3 downto 4*iga) or r.req_be;
314
315 if r.rdtag = r.req_addr(sa_f_ta) then -- invalidate rdbuf if same tag
316 n.rdval := '0';
317 end if;
318
319 -- ensure that at most 4 pending writes in queue
320 -- REQ_SIZE gives # of available slots, empty FIFO has REQ_SIZE=15
321 -- REQ_SIZE is 11 when 4 requests are on flight
322 if unsigned(REQ_SIZE) >= 11 then
323 n.actw := '0'; -- mark request done
324 iackw := '1'; -- send ack signal
325 end if;
326 end if;
327
328 -- handle read request
329 if r.actr = '1' then
330 if r.rdtag=r.req_addr(sa_f_ta) and r.rdval='1' then --
331 n.res_do := r.rdbuf(32*iga+31 downto 32*iga);
332 n.actr := '0'; -- mark request done
333 n.ackr := '1'; -- send ack signal
334 n.rdnew := '0'; -- mark used
335 imoni.rdrhit := not r.rdnew;
336 else
337 if r.wrpend /= pendzero then -- if write buffer pending
338 ireqena := '1'; -- queue write request
339 n.wrpend := pendzero; -- clear pending flags
340 imoni.wrflush := '1';
341 elsif r.rdpend = '0' then
342 ireqdi(rf_f_addr) := r.req_addr(sa_f_ta);
343 ireqdi(rf_f_we) := '0';
344 n.rdtag := r.req_addr(sa_f_ta); -- new tag
345 n.rdval := '0'; -- mark rdbuf invalid
346 n.rdpend := '1'; -- assert read pending
347 ireqena := '1'; -- queue read request
348 end if;
349 end if;
350 end if;
351
352 -- handle read response
353 if RES_VAL = '1' then
354 n.rdbuf := RES_DO; -- capture data
355 n.rdval := '1'; -- mark valid
356 n.rdnew := '1'; -- mark new
357 n.rdpend := '0'; -- deassert read pending
358 end if;
359
360 N_REGS <= n;
361
362 REQ_DI <= ireqdi;
363 REQ_ENA <= ireqena;
364 MONI <= imoni;
365
366 -- block input if busy or UI clock in RESET
367 BUSY <= r.actr or r.actw or MIGUIRST_CLK;
368
369 ACK_R <= r.ackr;
370 ACK_W <= iackw;
371 ACT_R <= r.actr;
372 ACT_W <= r.actw;
373 DO <= r.res_do;
374
375 end process proc_next;
376
377 proc_req2app: process (APP_RDY, APP_WDF_RDY, REQ_VAL, REQ_DO,
379 begin
380
381 REQ_HOLD <= '0';
382
383 APP_ADDR <= (others=>'0');
387
388 APP_EN <= '0';
389 APP_CMD <= c_migui_cmd_read;
390 APP_WDF_WREN <= '0';
391 APP_WDF_END <= '0';
392
393 if APP_RDY='1' and APP_WDF_RDY='1' and INIT_CALIB_COMPLETE='1' then
394 if REQ_VAL = '1' then
395 APP_EN <= '1';
396 if REQ_DO(rf_f_we) = '1' then
397 APP_CMD <= c_migui_cmd_write;
398 APP_WDF_WREN <= '1';
399 APP_WDF_END <= '1';
400 end if; -- REQ_DO(rf_f_we) = '1'
401 end if; -- REQ_VAL = '1'
402 else
403 REQ_HOLD <= '1';
404 end if; -- APP_RDY='1' and APP_WDF_RDY='1
405
406 end process proc_req2app;
407
408 proc_app2res: process (APP_RD_DATA_VALID, APP_RD_DATA)
409 begin
412 end process proc_app2res;
413
414end syn;
in DI slbit
in CLKO slbit
out DO slbit
std_logic_vector( 19 downto 0) slv20
Definition: slvtypes.vhd:53
std_logic_vector( 3 downto 0) slv4
Definition: slvtypes.vhd:36
std_logic_vector( 2 downto 0) slv3
Definition: slvtypes.vhd:35
std_logic_vector( 31 downto 0) slv32
Definition: slvtypes.vhd:59
std_logic slbit
Definition: slvtypes.vhd:30
std_logic_vector slv
Definition: slvtypes.vhd:31
positive := dwidth+ mwidth+ tawidth+ 1 rfwidth
integer range dwidth+ mwidth+ tawidth downto MWIDTH+ tawidth+ 1 rf_f_data
integer range BAWIDTH- 3 downto 0 sa_f_ga
integer range 20- 1 downto BAWIDTH- 2 sa_f_ta
slv( rfwidth- 1 downto 0) :=( others => '0') REQ_DI
positive := 8* mwidth dwidth
positive := 20-( BAWIDTH- 2) tawidth
positive := 2** BAWIDTH mwidth
slv4 :=( others => '0') REQ_SIZE
slv( dwidth- 1 downto 0) :=( others => '0') RES_DI
slv( mwidth- 1 downto 0) :=( others => '0') pendzero
regs_type := regs_init R_REGS
integer range tawidth downto 1 rf_f_addr
integer range mwidth+ tawidth downto tawidth+ 1 rf_f_mask
slv( dwidth- 1 downto 0) :=( others => '0') RES_DO
positive := 2**( BAWIDTH- 2) ngrp
slv( rfwidth- 1 downto 0) :=( others => '0') REQ_DO
integer range 22- 1 downto BAWIDTH ma_f_ta
regs_type :=( '0', '0', '0',( others => '0'),( others => '0'),( others => '0'),( others => '0'), bufzero, tagzero, '0', '0', '0', bufzero, tagzero, pendzero) regs_init
slv( dwidth- 1 downto 0) :=( others => '0') bufzero
slv( tawidth- 1 downto 0) :=( others => '0') tagzero
MAWIDTH positive := 28
in INIT_CALIB_COMPLETE slbit
out MONI sramif2migui_moni_type
in APP_RD_DATA slv( 8*( 2** BAWIDTH)- 1 downto 0)
out APP_WDF_DATA slv( 8*( 2** BAWIDTH)- 1 downto 0)
out APP_ADDR slv( MAWIDTH- 1 downto 0)
out APP_WDF_MASK slv(( 2** BAWIDTH)- 1 downto 0)
BAWIDTH positive := 4