1 |
37 |
wfjm |
-- $Id: mt45w8mw16b.vhd 799 2016-08-21 09:20:19Z mueller $
|
2 |
2 |
wfjm |
--
|
3 |
37 |
wfjm |
-- Copyright 2010-2016 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
4 |
2 |
wfjm |
--
|
5 |
|
|
-- This program is free software; you may redistribute and/or modify it under
|
6 |
|
|
-- the terms of the GNU General Public License as published by the Free
|
7 |
|
|
-- Software Foundation, either version 2, or at your option any later version.
|
8 |
|
|
--
|
9 |
|
|
-- This program is distributed in the hope that it will be useful, but
|
10 |
|
|
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
|
11 |
|
|
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
12 |
|
|
-- for complete details.
|
13 |
|
|
--
|
14 |
|
|
------------------------------------------------------------------------------
|
15 |
|
|
-- Module Name: mt45w8mw16b - sim
|
16 |
|
|
-- Description: Micron MT45W8MW16B CellularRAM model
|
17 |
|
|
-- Currently a much simplified model
|
18 |
|
|
-- - only async accesses
|
19 |
37 |
wfjm |
-- - ignores CLK
|
20 |
2 |
wfjm |
-- - simple model for response of DATA lines, but no
|
21 |
|
|
-- check for timing violations of control lines
|
22 |
|
|
--
|
23 |
|
|
-- Dependencies: -
|
24 |
|
|
-- Test bench: -
|
25 |
|
|
-- Target Devices: generic
|
26 |
37 |
wfjm |
-- Tool versions: xst 11.4-14.7; ghdl 0.26-0.33
|
27 |
2 |
wfjm |
-- Revision History:
|
28 |
|
|
-- Date Rev Version Comment
|
29 |
37 |
wfjm |
-- 2016-08-18 799 1.4.1 remove 'assert false' from report statements
|
30 |
|
|
-- 2016-07-10 786 1.4 add RCR handling; page mode by default now off !!
|
31 |
34 |
wfjm |
-- 2015-12-26 718 1.3.3 BUGFIX: initialize L_ADDR with all '1', see comment
|
32 |
13 |
wfjm |
-- 2011-11-19 427 1.3.2 now numeric_std clean
|
33 |
2 |
wfjm |
-- 2010-06-03 299 1.3.1 improved timing model (WE cycle, robust T_apa)
|
34 |
|
|
-- 2010-06-03 298 1.3 add timing model again
|
35 |
|
|
-- 2010-05-28 295 1.2 drop timing (was incorrect), pure functional now
|
36 |
|
|
-- 2010-05-21 293 1.1 add BCR (only read of default so far)
|
37 |
|
|
-- 2010-05-16 291 1.0 Initial version (inspired by is61lv25616al)
|
38 |
|
|
------------------------------------------------------------------------------
|
39 |
|
|
-- Truth table accoring to data sheet:
|
40 |
|
|
--
|
41 |
|
|
-- Asynchronous Mode (BCR(15)=1)
|
42 |
|
|
-- Operation CLK ADV_N CE_N OE_N WE_N CRE xB_N WT DATA
|
43 |
|
|
-- Read L L L L H L L act data-out
|
44 |
|
|
-- Write L L L X L L L act data-in
|
45 |
|
|
-- Standby L X H X X L X 'z' 'z'
|
46 |
|
|
-- CRE write L L L H L H X act 'z'
|
47 |
|
|
-- CRE read L L L L H H L act conf-out
|
48 |
|
|
--
|
49 |
|
|
-- Burst Mode (BCR(15)=0)
|
50 |
|
|
-- Operation CLK ADV_N CE_N OE_N WE_N CRE xB_N WT DATA
|
51 |
|
|
-- Async read L L L L H L L act data-out
|
52 |
|
|
-- Async write L L L X L L L act data-in
|
53 |
|
|
-- Standby L X H X X L X 'z' 'z'
|
54 |
|
|
-- Initial burst read 0-1 L L X H L L act X
|
55 |
|
|
-- Initial burst write 0-1 L L H L L X act X
|
56 |
|
|
-- Burst continue 0-1 H L X X X X act data-in/out
|
57 |
|
|
-- CRE write 0-1 L L H L H X act 'z'
|
58 |
|
|
-- CRE read 0-1 L L L H H L act conf-out
|
59 |
|
|
--
|
60 |
|
|
|
61 |
|
|
library ieee;
|
62 |
|
|
use ieee.std_logic_1164.all;
|
63 |
13 |
wfjm |
use ieee.numeric_std.all;
|
64 |
2 |
wfjm |
|
65 |
|
|
use work.slvtypes.all;
|
66 |
|
|
|
67 |
|
|
entity mt45w8mw16b is -- Micron MT45W8MW16B CellularRAM model
|
68 |
|
|
port (
|
69 |
|
|
CLK : in slbit; -- clock for synchonous operation
|
70 |
|
|
CE_N : in slbit; -- chip enable (act.low)
|
71 |
|
|
OE_N : in slbit; -- output enable (act.low)
|
72 |
|
|
WE_N : in slbit; -- write enable (act.low)
|
73 |
|
|
UB_N : in slbit; -- upper byte enable (act.low)
|
74 |
|
|
LB_N : in slbit; -- lower byte enable (act.low)
|
75 |
|
|
ADV_N : in slbit; -- address valid (act.low)
|
76 |
|
|
CRE : in slbit; -- control register enable
|
77 |
|
|
MWAIT : out slbit; -- wait (for burst read/write)
|
78 |
|
|
ADDR : in slv23; -- address lines
|
79 |
|
|
DATA : inout slv16 -- data lines
|
80 |
|
|
);
|
81 |
|
|
end mt45w8mw16b;
|
82 |
|
|
|
83 |
|
|
|
84 |
|
|
architecture sim of mt45w8mw16b is
|
85 |
|
|
|
86 |
|
|
-- timing constants for -701 speed grade (70 ns; 104 MHz)
|
87 |
37 |
wfjm |
constant T_aa : Delay_length := 70 ns; -- address access time (max)
|
88 |
|
|
constant T_apa : Delay_length := 20 ns; -- page access time (max)
|
89 |
|
|
constant T_oh : Delay_length := 5 ns; -- output hold from addr change (max)
|
90 |
|
|
constant T_oe : Delay_length := 20 ns; -- output enable to valid output (max)
|
91 |
|
|
constant T_ohz : Delay_length := 8 ns; -- output disable to high-z out (max)
|
92 |
|
|
constant T_olz : Delay_length := 3 ns; -- output enable to low-z output (min)
|
93 |
|
|
constant T_lz : Delay_length := 10 ns; -- chip enable to low-z output (min)
|
94 |
|
|
constant T_hz : Delay_length := 8 ns; -- chip disable to high-z output (max)
|
95 |
2 |
wfjm |
|
96 |
|
|
constant memsize : positive := 2**(ADDR'length);
|
97 |
|
|
constant datzero : slv(DATA'range) := (others=>'0');
|
98 |
|
|
type ram_type is array (0 to memsize-1) of slv(DATA'range);
|
99 |
|
|
|
100 |
37 |
wfjm |
subtype xcr_f_sel is integer range 19 downto 18; -- cre register select
|
101 |
|
|
constant xcr_sel_rcr : slv2 := "00";
|
102 |
|
|
constant xcr_sel_bcr : slv2 := "10";
|
103 |
|
|
|
104 |
2 |
wfjm |
constant bcr_f_mode : integer := 15; -- operating mode
|
105 |
|
|
constant bcr_f_ilat : integer := 14; -- initial latency
|
106 |
|
|
subtype bcr_f_lc is integer range 13 downto 11; -- latency counter
|
107 |
|
|
constant bcr_f_wp : integer := 10; -- wait polarity
|
108 |
|
|
constant bcr_f_wc : integer := 8; -- wait configuration
|
109 |
|
|
subtype bcr_f_drive is integer range 5 downto 4; -- drive strength
|
110 |
|
|
constant bcr_f_bw : integer := 3; -- burst wrap
|
111 |
|
|
subtype bcr_f_bl is integer range 2 downto 0; -- burst length
|
112 |
37 |
wfjm |
|
113 |
|
|
subtype rcr_f_res3 is integer range 22 downto 20; -- reserved - MBZ
|
114 |
|
|
subtype rcr_f_res2 is integer range 17 downto 8; -- reserved - MBZ
|
115 |
|
|
constant rcr_f_pmode : integer := 7; -- page mode (1=ena)
|
116 |
|
|
subtype rcr_f_res1 is integer range 6 downto 5; -- reserved - MBZ
|
117 |
|
|
constant rcr_f_dpd : integer := 4; -- dpd mode (1=dis)
|
118 |
|
|
constant rcr_f_res0 : integer := 3; -- reserved - MBZ
|
119 |
|
|
subtype rcr_f_par is integer range 2 downto 0; -- array conf (000=all)
|
120 |
2 |
wfjm |
|
121 |
|
|
subtype f_byte1 is integer range 15 downto 8;
|
122 |
|
|
subtype f_byte0 is integer range 7 downto 0;
|
123 |
|
|
|
124 |
|
|
signal CE : slbit := '0';
|
125 |
|
|
signal OE : slbit := '0';
|
126 |
|
|
signal WE : slbit := '0';
|
127 |
|
|
signal BE_L : slbit := '0';
|
128 |
|
|
signal BE_U : slbit := '0';
|
129 |
|
|
signal ADV : slbit := '0';
|
130 |
|
|
signal WE_L_EFF : slbit := '0';
|
131 |
|
|
signal WE_U_EFF : slbit := '0';
|
132 |
37 |
wfjm |
signal WE_C_EFF : slbit := '0';
|
133 |
2 |
wfjm |
|
134 |
|
|
signal R_BCR_MODE : slbit := '1'; -- mode: def: async
|
135 |
|
|
signal R_BCR_ILAT : slbit := '0'; -- ilat: def: variable
|
136 |
|
|
signal R_BCR_LC : slv3 := "011"; -- lc: def: code 3
|
137 |
|
|
signal R_BCR_WP : slbit := '1'; -- wp: def: active high
|
138 |
|
|
signal R_BCR_WC : slbit := '1'; -- wc: def: assert one before
|
139 |
|
|
signal R_BCR_DRIVE : slv2 := "01"; -- drive:def: 1/2
|
140 |
|
|
signal R_BCR_BW : slbit := '1'; -- bw: def: no wrap
|
141 |
|
|
signal R_BCR_BL : slv3 := "111"; -- bl: def: continuous
|
142 |
37 |
wfjm |
|
143 |
|
|
signal R_RCR_PMODE : slbit := '0'; -- pmode:def: disabled (ena=1 !)
|
144 |
|
|
signal R_RCR_DPD : slbit := '1'; -- dpd: def: disabled (ena=0 !)
|
145 |
|
|
signal R_RCR_PAR : slv3 := "000"; -- par: def: full array
|
146 |
|
|
signal R_T_APA_EFF : Delay_length := T_aa; -- page mode disabled by default
|
147 |
|
|
|
148 |
34 |
wfjm |
signal L_ADDR : slv23 := (others=>'1'); -- all '1' for propper 1st access
|
149 |
2 |
wfjm |
signal DOUT_VAL_EN : slbit := '0';
|
150 |
|
|
signal DOUT_VAL_AA : slbit := '0';
|
151 |
|
|
signal DOUT_VAL_PA : slbit := '0';
|
152 |
|
|
signal DOUT_VAL_OE : slbit := '0';
|
153 |
|
|
signal DOUT_LZ_CE : slbit := '0';
|
154 |
|
|
signal DOUT_LZ_OE : slbit := '0';
|
155 |
|
|
|
156 |
|
|
signal OEWE : slbit := '0';
|
157 |
|
|
signal DOUT : slv16 := (others=>'0');
|
158 |
|
|
begin
|
159 |
|
|
|
160 |
|
|
CE <= not CE_N;
|
161 |
|
|
OE <= not OE_N;
|
162 |
|
|
WE <= not WE_N;
|
163 |
|
|
BE_L <= not LB_N;
|
164 |
|
|
BE_U <= not UB_N;
|
165 |
|
|
ADV <= not ADV_N;
|
166 |
|
|
|
167 |
37 |
wfjm |
WE_L_EFF <= CE and WE and BE_L and (not CRE);
|
168 |
|
|
WE_U_EFF <= CE and WE and BE_U and (not CRE);
|
169 |
2 |
wfjm |
|
170 |
37 |
wfjm |
WE_C_EFF <= CE and WE and CRE;
|
171 |
|
|
|
172 |
2 |
wfjm |
-- address valid logic, latch ADDR when ADV true
|
173 |
|
|
proc_adv: process (ADV, ADDR)
|
174 |
|
|
begin
|
175 |
|
|
if ADV = '1' then
|
176 |
|
|
L_ADDR <= ADDR;
|
177 |
|
|
end if;
|
178 |
|
|
end process proc_adv;
|
179 |
|
|
|
180 |
34 |
wfjm |
-- Notes:
|
181 |
|
|
-- 1. the row change (t_aa) and column change (t_apa) timing depends on the
|
182 |
|
|
-- recognition of address changes and of page changes. To keep the logic
|
183 |
|
|
-- simple L_ADDR and addr_last are initialized with all '1'. This gives
|
184 |
|
|
-- proper behaviour unless the very first access uses the very last
|
185 |
|
|
-- address. In w11a systems, with use only 4 MB, this can't happen, in
|
186 |
|
|
-- most other use cases this is very unlikely.
|
187 |
|
|
|
188 |
2 |
wfjm |
proc_dout_val: process (CE, OE, WE, BE_L, BE_U, ADV, L_ADDR)
|
189 |
34 |
wfjm |
variable addr_last : slv23 := (others=>'1');-- all '1' for propper 1st access
|
190 |
2 |
wfjm |
begin
|
191 |
|
|
if (CE'event and CE='1') or
|
192 |
|
|
(BE_L'event and BE_L='1') or
|
193 |
|
|
(BE_U'event and BE_U='1') or
|
194 |
|
|
(WE'event and WE='0') or
|
195 |
|
|
(ADV'event and ADV='1') then
|
196 |
|
|
DOUT_VAL_EN <= '0', '1' after T_aa;
|
197 |
|
|
end if;
|
198 |
|
|
if L_ADDR'event then
|
199 |
37 |
wfjm |
DOUT_VAL_PA <= '0', '1' after R_T_APA_EFF;
|
200 |
2 |
wfjm |
if L_ADDR(22 downto 4) /= addr_last(22 downto 4) then
|
201 |
|
|
DOUT_VAL_AA <= '0', '1' after T_aa;
|
202 |
|
|
end if;
|
203 |
|
|
addr_last := L_ADDR;
|
204 |
|
|
end if;
|
205 |
13 |
wfjm |
if rising_edge(OE) then
|
206 |
2 |
wfjm |
DOUT_VAL_OE <= '0', '1' after T_oe;
|
207 |
|
|
end if;
|
208 |
|
|
end process proc_dout_val;
|
209 |
|
|
|
210 |
|
|
-- to simplify things assume that OE and (not WE) have same effect on output
|
211 |
|
|
-- drivers. The timing rules are very similar indeed...
|
212 |
|
|
OEWE <= OE and (not WE);
|
213 |
|
|
|
214 |
|
|
proc_dout_lz: process (CE, OEWE)
|
215 |
|
|
begin
|
216 |
|
|
if (CE'event) then
|
217 |
|
|
if CE = '1' then
|
218 |
|
|
DOUT_LZ_CE <= '1' after T_lz;
|
219 |
|
|
else
|
220 |
|
|
DOUT_LZ_CE <= '0' after T_hz;
|
221 |
|
|
end if;
|
222 |
|
|
end if;
|
223 |
|
|
if (OEwe'event) then
|
224 |
|
|
if OEWE = '1' then
|
225 |
|
|
DOUT_LZ_OE <= '1' after T_olz;
|
226 |
|
|
else
|
227 |
|
|
DOUT_LZ_OE <= '0' after T_ohz;
|
228 |
|
|
end if;
|
229 |
|
|
end if;
|
230 |
|
|
end process proc_dout_lz;
|
231 |
|
|
|
232 |
37 |
wfjm |
proc_cram: process (WE_L_EFF, WE_U_EFF, L_ADDR, DATA)
|
233 |
2 |
wfjm |
variable ram : ram_type := (others=>datzero);
|
234 |
|
|
begin
|
235 |
|
|
|
236 |
|
|
-- end of write cycle
|
237 |
|
|
-- note: to_x01 used below to prevent that 'z' a written into mem.
|
238 |
13 |
wfjm |
if falling_edge(WE_L_EFF) then
|
239 |
|
|
ram(to_integer(unsigned(L_ADDR)))(f_byte0) := to_x01(DATA(f_byte0));
|
240 |
2 |
wfjm |
end if;
|
241 |
13 |
wfjm |
if falling_edge(WE_U_EFF) then
|
242 |
|
|
ram(to_integer(unsigned(L_ADDR)))(f_byte1) := to_x01(DATA(f_byte1));
|
243 |
2 |
wfjm |
end if;
|
244 |
|
|
|
245 |
13 |
wfjm |
DOUT <= ram(to_integer(unsigned(L_ADDR)));
|
246 |
2 |
wfjm |
|
247 |
|
|
end process proc_cram;
|
248 |
|
|
|
249 |
37 |
wfjm |
proc_cr: process (WE_C_EFF, L_ADDR)
|
250 |
|
|
begin
|
251 |
|
|
if falling_edge(WE_C_EFF) then
|
252 |
|
|
case L_ADDR(xcr_f_sel) is
|
253 |
|
|
|
254 |
|
|
when xcr_sel_rcr =>
|
255 |
|
|
R_RCR_PMODE <= L_ADDR(rcr_f_pmode);
|
256 |
|
|
if L_ADDR(rcr_f_pmode) = '1' then
|
257 |
|
|
R_T_APA_EFF <= T_apa;
|
258 |
|
|
else
|
259 |
|
|
R_T_APA_EFF <= T_aa;
|
260 |
|
|
end if;
|
261 |
|
|
assert L_ADDR(rcr_f_res3) = "000"
|
262 |
|
|
report "bad rcr write: 22:20 not zero" severity error;
|
263 |
|
|
assert L_ADDR(rcr_f_res2) = "0000000000"
|
264 |
|
|
report "bad rcr write: 17: 8 not zero" severity error;
|
265 |
|
|
assert L_ADDR(rcr_f_res1) = "00"
|
266 |
|
|
report "bad rcr write: 6: 5 not zero" severity error;
|
267 |
|
|
assert L_ADDR(rcr_f_dpd) = '1'
|
268 |
|
|
report "bad rcr write: dpd not '1'" severity error;
|
269 |
|
|
assert L_ADDR(rcr_f_res0) = '0'
|
270 |
|
|
report "bad rcr write: 3: 3 not zero" severity error;
|
271 |
|
|
assert L_ADDR(rcr_f_par) = "000"
|
272 |
|
|
report "bad rcr write: par not '000'" severity error;
|
273 |
|
|
|
274 |
|
|
when xcr_sel_bcr =>
|
275 |
|
|
report "bcr written - not supported" severity error;
|
276 |
|
|
when others =>
|
277 |
|
|
report "bad select field" severity error;
|
278 |
|
|
end case;
|
279 |
|
|
end if;
|
280 |
|
|
end process proc_cr;
|
281 |
|
|
|
282 |
2 |
wfjm |
proc_data: process (DOUT, DOUT_VAL_EN, DOUT_VAL_AA, DOUT_VAL_PA, DOUT_VAL_OE,
|
283 |
|
|
DOUT_LZ_CE, DOUT_LZ_OE)
|
284 |
|
|
variable idout : slv16 := (others=>'0');
|
285 |
|
|
begin
|
286 |
|
|
idout := DOUT;
|
287 |
|
|
if DOUT_VAL_EN='0' or DOUT_VAL_AA='0' or
|
288 |
|
|
DOUT_VAL_PA='0' or DOUT_VAL_OE='0' then
|
289 |
|
|
idout := (others=>'X');
|
290 |
|
|
end if;
|
291 |
|
|
if DOUT_LZ_CE='0' or DOUT_LZ_OE='0' then
|
292 |
|
|
idout := (others=>'Z');
|
293 |
|
|
end if;
|
294 |
|
|
DATA <= idout;
|
295 |
|
|
end process proc_data;
|
296 |
|
|
|
297 |
|
|
proc_mwait: process (CE)
|
298 |
|
|
begin
|
299 |
|
|
-- WT driver (just a dummy)
|
300 |
|
|
if CE = '1' then
|
301 |
|
|
MWAIT <= '1';
|
302 |
|
|
else
|
303 |
|
|
MWAIT <= 'Z';
|
304 |
|
|
end if;
|
305 |
|
|
end process proc_mwait;
|
306 |
|
|
|
307 |
|
|
end sim;
|