w11 - vhd 0.794
W11 CPU core and support modules
Loading...
Searching...
No Matches
migui_core_gsim.vhd
Go to the documentation of this file.
1-- $Id: migui_core_gsim.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: migui_core_gsim - sim
7-- Description: MIG interface simulation core
8--
9-- Dependencies: sfs_gsim_core
10-- Test bench: tb/tb_sramif2migui_core
11-- Target Devices: generic
12-- Tool versions: viv 2017.2; ghdl 0.34
13--
14-- Revision History:
15-- Date Rev Version Comment
16-- 2018-12-28 1096 1.0 Initial version
17-- 2018-11-10 1067 0.1 First draft
18--
19------------------------------------------------------------------------------
20
21library ieee;
22use ieee.std_logic_1164.all;
23use ieee.numeric_std.all;
24
25use work.slvtypes.all;
26use work.xlib.all;
27use work.miglib.all;
28
29entity migui_core_gsim is -- MIG interface simulation core
30 generic (
31 BAWIDTH : positive := 4; -- byte address width
32 MAWIDTH : positive := 28; -- memory address width
33 SAWIDTH : positive := 24; -- simulator memory address width
34 CLKMUI_MUL : positive := 6; -- multiplier for MIG UI clock
35 CLKMUI_DIV : positive := 12; -- divider for MIG UI clock
36 CACO_WAIT : positive := 50); -- UI_CLK cycles till CALIB_COMP = 1
37 port (
38 SYS_CLK : in slbit; -- system clock
39 SYS_RST : in slbit; -- system reset
40 UI_CLK : out slbit; -- MIGUI clock
41 UI_CLK_SYNC_RST : out slbit; -- MIGUI reset
42 INIT_CALIB_COMPLETE : out slbit; -- MIGUI calibration done
43 APP_RDY : out slbit; -- MIGUI ready for cmd
44 APP_EN : in slbit; -- MIGUI command enable
45 APP_CMD : in slv3; -- MIGUI command
46 APP_ADDR : in slv(MAWIDTH-1 downto 0); -- MIGUI address
47 APP_WDF_RDY : out slbit; -- MIGUI ready for data write
48 APP_WDF_WREN : in slbit; -- MIGUI data write enable
49 APP_WDF_DATA : in slv(8*(2**BAWIDTH)-1 downto 0);-- MIGUI write data
50 APP_WDF_MASK : in slv((2**BAWIDTH)-1 downto 0); -- MIGUI write mask
51 APP_WDF_END : in slbit; -- MIGUI write end
52 APP_RD_DATA_VALID : out slbit; -- MIGUI read valid
53 APP_RD_DATA : out slv(8*(2**BAWIDTH)-1 downto 0);-- MIGUI read data
54 APP_RD_DATA_END : out slbit; -- MIGUI read end
55 APP_REF_REQ : in slbit; -- MIGUI refresh request
56 APP_ZQ_REQ : in slbit; -- MIGUI ZQ calibrate request
57 APP_REF_ACK : out slbit; -- MIGUI refresh acknowledge
58 APP_ZQ_ACK : out slbit -- MIGUI ZQ calibrate acknowledge
59 );
61
62
63architecture sim of migui_core_gsim is
64
65 constant mwidth : positive := 2**BAWIDTH; -- mask width (8 or 16)
66 constant dwidth : positive := 8*mwidth; -- data width (64 or 128)
67
68 -- row/col split only relevant for timing simulation
69 -- use 16kbit->2kByte column width as used in MT41K128M16 on arty board
70 constant colwidth : positive := 11;
71 constant rowwidth : positive := MAWIDTH-colwidth;
72 subtype addr_f_row is integer range MAWIDTH-1 downto colwidth;
73
74 subtype bv8 is bit_vector(7 downto 0);
75 constant memsize : positive := 2**SAWIDTH;
76 constant datzero : bv8 := (others=>'0');
77 type ram_type is array (0 to memsize-1) of bv8;
78
79 -- timing constants
80 constant c_rdwait_rhit : positive := 2; -- read wait row match
81 constant c_rdwait_rmis : positive := 5; -- read wait row miss
82 constant c_wrwait_rhit : positive := 2; -- write wait row match
83 constant c_wrwait_rmis : positive := 5; -- write wait row miss
84 constant c_wrwait_max : positive := c_wrwait_rmis; -- write wait maximum
85 -- the REF and ZQ delays are as observed for arty board
86 constant c_refwait : positive := 10; -- REF_REQ to REF_ACK delay
87 constant c_zqwait : positive := 8; -- ZQ_REQ to ZQ_ACK delay
88 -- the RDY pattern gives 23% busy (4 out of 13 cycles)
89 -- good enough for simulation; observed pattern on arty shows ~6% busy,
90 constant c_crdy_init : slv13 := "0001111110111"; -- block 4 of 13;
91
92 type regs_type is record
93 cacowait : natural; -- CACO wait down counter
94 enacaco : slbit; -- CACO enable
95 enardy : slbit; -- RDY enable
96 rowaddr : slv(rowwidth-1 downto 0); -- current row address
97 rdwait : natural; -- read wait cycles pending
98 wrwait : natural; -- write wait cycles pending
99 crdypat : slv13; -- crdy pattern
100 refwait : natural; -- req_ack wait counter
101 zqwait : natural; -- zq_ack wait counter
102 end record regs_type;
103
104 constant rowaddr_init : slv(rowwidth-1 downto 0) := (others=>'1');
105
106 constant regs_init : regs_type := (
107 CACO_WAIT,'0','0', -- cacowait,enacaco,enardy
108 rowaddr_init, -- rowaddr
109 0,0, -- rdwait,wrwait
110 c_crdy_init, -- crdypat
111 0,0 -- refwait,zqwait
112 );
113
114 signal CLK : slbit; -- local copy of UI_CLK
115
117 signal N_REGS : regs_type; -- don't init (vivado fix for fsm infer)
118
119 signal CLKFX : slbit;
120
121 signal MEM_EN : slbit := '0'; -- sim mem enable
122 signal MEM_WE : slbit := '0'; -- sim mem write enable
123 signal MEM_ADDR : slv(SAWIDTH-BAWIDTH-1 downto 0); -- sim mem base address
124 signal R_MEMDO : slv(dwidth-1 downto 0) := (others=>'0');
125
126
127begin
128
129 assert BAWIDTH = 3 or BAWIDTH = 4
130 report "assert( BAWIDTH = 3 or 4 )"
131 severity failure;
132
133 UICLKGEN : sfs_gsim_core -- mig ui clock generator
134 generic map (
135 VCO_DIVIDE => 1,
136 VCO_MULTIPLY => CLKMUI_MUL,
137 OUT_DIVIDE => CLKMUI_DIV)
138 port map (
139 CLKIN => SYS_CLK,
140 CLKFX => CLKFX,
141 LOCKED => open
142 );
143
144 CLK <= CLKFX; -- !! copy both local CLK and exported
145 UI_CLK <= CLKFX; -- !! UI_CLK to avoid delta cycle diff
146 UI_CLK_SYNC_RST <= '0';
147
148 proc_regs: process (CLK)
149 begin
150
151 if rising_edge(CLK) then
152 if SYS_RST = '1' then
153 R_REGS <= regs_init;
154 else
155 R_REGS <= N_REGS;
156 end if;
157 end if;
158
159 end process proc_regs;
160
161 proc_next: process (R_REGS, APP_EN, APP_ADDR, APP_CMD,
164
165 variable r : regs_type := regs_init;
166 variable n : regs_type := regs_init;
167
168 variable iappcrdy : slbit := '0';
169 variable iappwrdy : slbit := '0';
170 variable iapprefack : slbit := '0';
171 variable iappzqack : slbit := '0';
172 variable imemen : slbit := '0';
173 variable imemwe : slbit := '0';
174 variable irdval : slbit := '0';
175
176 begin
177
178 r := R_REGS;
179 n := R_REGS;
180
181 iappcrdy := '1';
182 iappwrdy := '1';
183 iapprefack := '0';
184 iappzqack := '0';
185 imemen := '0';
186 imemwe := '0';
187 irdval := '0';
188
189 n.crdypat := r.crdypat(11 downto 0) & r.crdypat(12); -- circular right shift
190
191 -- simulate CACO wait
192 if r.cacowait > 0 then
193 n.cacowait := r.cacowait - 1;
194 if r.cacowait <= CACO_WAIT/2 then -- half of CACO wait reached ?
195 n.enardy := '1'; -- enable RDY's
196 end if;
197 if r.cacowait = 1 then -- CACO wait ended ?
198 n.enacaco := '1'; -- assert CACO
199 end if;
200 end if;
201
202 -- process cmd requests
203 if r.wrwait >= c_wrwait_max then
204 iappcrdy := '0';
205 iappwrdy := '0';
206 elsif r.rdwait > 0 then
207 iappcrdy := '0';
208 elsif r.enardy='0' or r.crdypat(0)='0' then
209 iappcrdy := '0';
210
211 else
212 if APP_EN = '1' then
213 if APP_CMD = c_migui_cmd_read then
214 imemen := '1';
215 if r.rowaddr = APP_ADDR(addr_f_row) then
216 n.rdwait := r.rdwait + c_rdwait_rhit;
217 else
218 n.rdwait := r.rdwait + c_rdwait_rmis;
219 n.rowaddr := APP_ADDR(addr_f_row);
220 end if;
221 elsif APP_CMD = c_migui_cmd_write then
222 imemen := '1';
223 imemwe := '1';
224 if r.rowaddr = APP_ADDR(addr_f_row) then
225 n.wrwait := r.wrwait + c_wrwait_rhit;
226 else
227 n.wrwait := r.wrwait + c_wrwait_rmis;
228 n.rowaddr := APP_ADDR(addr_f_row);
229 end if;
230 else
231 end if;
232 end if;
233 end if;
234
235 -- handle cmd waits, issue read responses
236 if r.enacaco = '1' then -- process commands only after CACO
237 if r.wrwait > 0 then -- first wait for pending writes
238 n.wrwait := r.wrwait - 1;
239 else
240 if r.rdwait > 0 then -- next of for pending reads
241 n.rdwait := r.rdwait - 1;
242 if r.rdwait = 1 then
243 irdval := '1';
244 end if;
245 end if;
246 end if;
247 end if;
248
249 -- process ref_req requests
250 if APP_REF_REQ = '1' then
251 n.refwait := c_refwait;
252 else
253 if r.refwait > 0 then
254 n.refwait := r.refwait -1;
255 if r.refwait = 1 then
256 iapprefack := '1';
257 end if;
258 end if;
259 end if;
260
261 -- process zq_req requests
262 if APP_ZQ_REQ = '1' then
263 n.zqwait := c_zqwait;
264 else
265 if r.zqwait > 0 then
266 n.zqwait := r.zqwait -1;
267 if r.zqwait = 1 then
268 iappzqack := '1';
269 end if;
270 end if;
271 end if;
272
273 N_REGS <= n;
274
275 INIT_CALIB_COMPLETE <= r.enacaco;
276
277 APP_RDY <= iappcrdy;
278 APP_WDF_RDY <= iappwrdy;
279 APP_RD_DATA_VALID <= irdval;
280 APP_RD_DATA_END <= irdval;
281 APP_REF_ACK <= iapprefack;
282 APP_ZQ_ACK <= iappzqack;
283 if irdval = '1' then -- only in the RD_DATA_END cycle
284 APP_RD_DATA <= R_MEMDO; -- export the data
285 else -- otherwise
286 APP_RD_DATA <= (others=>'1'); -- send all ones
287 end if;
288 MEM_EN <= imemen;
289 MEM_WE <= imemwe;
290 MEM_ADDR <= APP_ADDR(SAWIDTH-1 downto BAWIDTH);
291
292 end process proc_next;
293
294 proc_mem: process (CLK)
295 variable ram : ram_type := (others=>datzero);
296 variable membase : integer := 0;
297 begin
298 if rising_edge(CLK) then
299 if MEM_EN = '1' then
300 membase := mwidth*to_integer(unsigned(MEM_ADDR));
301 -- write to memory
302 if APP_WDF_WREN = '1' then
303 for i in 0 to mwidth-1 loop
304 if APP_WDF_MASK(i) = '0' then -- WE = not MASK !!
305 ram(membase + i) :=
306 to_bitvector(to_x01(APP_WDF_DATA(8*i+7 downto 8*i)));
307 end if;
308 end loop;
309 end if;
310 -- read from memory
311 for i in 0 to mwidth-1 loop
312 R_MEMDO(8*i+7 downto 8*i) <= to_stdlogicvector(ram(membase + i));
313 end loop;
314
315 end if;
316 end if;
317 end process proc_mem;
318
319 proc_moni: process (CLK)
320 begin
321 if rising_edge(CLK) then
322 if SYS_RST = '0' then
323 if APP_EN = '1' then
324 assert APP_CMD = c_migui_cmd_read or
325 APP_CMD = c_migui_cmd_write
326 report "migui_core_gsim: FAIL: APP_CMD not 000 or 001"
327 severity error;
328
329 assert unsigned(APP_ADDR(MAWIDTH-1 downto SAWIDTH)) = 0
330 report "migui_core_gsim: FAIL: out of sim-memory size access"
331 severity error;
332 end if;
333
334 if APP_EN = '1' and APP_CMD = c_migui_cmd_write then
335 assert APP_WDF_WREN='1' and APP_WDF_END='1'
336 report "migui_core_gsim: FAIL: APP_WDF_(END,WREN) missed on write"
337 severity error;
338 else
339 assert APP_WDF_WREN='0' and APP_WDF_END='0'
340 report "migui_core_gsim: FAIL: spurious APP_WDF_(END,WREN)"
341 severity error;
342 end if;
343 end if;
344 end if;
345 end process proc_moni;
346
347end sim;
( 0 to memsize- 1) bv8 ram_type
positive := 11 colwidth
positive := 8 c_zqwait
positive := MAWIDTH- colwidth rowwidth
bv8 :=( others => '0') datzero
slv( dwidth- 1 downto 0) :=( others => '0') R_MEMDO
positive := 8* mwidth dwidth
positive := 2** BAWIDTH mwidth
positive := 5 c_rdwait_rmis
slv( SAWIDTH- BAWIDTH- 1 downto 0) MEM_ADDR
slv( rowwidth- 1 downto 0) :=( others => '1') rowaddr_init
regs_type :=( CACO_WAIT, '0', '0', rowaddr_init, 0, 0, c_crdy_init, 0, 0) regs_init
slv13 := "0001111110111" c_crdy_init
integer range MAWIDTH- 1 downto colwidth addr_f_row
regs_type := regs_init R_REGS
positive := c_wrwait_rmis c_wrwait_max
positive := 2 c_wrwait_rhit
positive := 2** SAWIDTH memsize
bit_vector( 7 downto 0) bv8
positive := 2 c_rdwait_rhit
positive := 5 c_wrwait_rmis
positive := 10 c_refwait
MAWIDTH positive := 28
out APP_RDY slbit
out APP_RD_DATA_VALID slbit
out APP_REF_ACK slbit
out APP_RD_DATA_END slbit
in APP_WDF_MASK slv(( 2** BAWIDTH)- 1 downto 0)
CLKMUI_MUL positive := 6
SAWIDTH positive := 24
in APP_WDF_DATA slv( 8*( 2** BAWIDTH)- 1 downto 0)
CACO_WAIT positive := 50
in APP_WDF_END slbit
out INIT_CALIB_COMPLETE slbit
out APP_RD_DATA slv( 8*( 2** BAWIDTH)- 1 downto 0)
in APP_REF_REQ slbit
out APP_ZQ_ACK slbit
out APP_WDF_RDY slbit
in APP_ZQ_REQ slbit
CLKMUI_DIV positive := 12
in APP_WDF_WREN slbit
in APP_ADDR slv( MAWIDTH- 1 downto 0)
BAWIDTH positive := 4
out UI_CLK_SYNC_RST slbit
std_logic_vector( 12 downto 0) slv13
Definition: slvtypes.vhd:45
std_logic_vector( 2 downto 0) slv3
Definition: slvtypes.vhd:35
std_logic slbit
Definition: slvtypes.vhd:30
std_logic_vector slv
Definition: slvtypes.vhd:31
Definition: xlib.vhd:35