forked from xesscorp/VHDL_Lib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MemTest.vhd
268 lines (236 loc) · 11.9 KB
/
MemTest.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
--**********************************************************************
-- Copyright (c) 1997-2014 by XESS Corp <http://www.xess.com>.
-- All rights reserved.
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 3.0 of the License, or (at your option) any later version.
--
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public
-- License along with this library. If not, see
-- <http://www.gnu.org/licenses/>.
--**********************************************************************
--------------------------------------------------------------------
-- Memory-testing routine
--------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
package MemTestPckg is
component MemTest is
generic(
PIPE_EN_G : boolean := false; -- enable pipelined operations
DATA_WIDTH_G : natural := 16; -- memory data width
ADDR_WIDTH_G : natural := 23; -- memory address width
BEG_TEST_G : natural := 16#00_0000#; -- beginning test range address
END_TEST_G : natural := 16#7F_FFFF# -- ending test range address
);
port(
clk_i : in std_logic; -- master clock input
rst_i : in std_logic; -- reset
doAgain_i : in std_logic; -- re-do memory test
begun_i : in std_logic; -- memory operation begun_i indicator
done_i : in std_logic; -- memory operation done_i indicator
dIn_i : in std_logic_vector(DATA_WIDTH_G-1 downto 0); -- data from memory
rdPending_i : in std_logic; -- read operations in progress_o indicator
rd_o : out std_logic; -- memory read control signal
wr_o : out std_logic; -- memory write control signal
addr_o : out std_logic_vector(ADDR_WIDTH_G-1 downto 0); -- address to memory
dOut_o : out std_logic_vector(DATA_WIDTH_G-1 downto 0); -- data to memory
progress_o : out std_logic_vector(1 downto 0); -- memory test progress_o indicator
err_o : out std_logic -- memory error flag
);
end component;
end package;
library IEEE, XESS;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use XESS.CommonPckg.all;
use XESS.RandPckg.all;
entity MemTest is
generic(
PIPE_EN_G : boolean := false; -- enable pipelined operations
DATA_WIDTH_G : natural := 16; -- memory data width
ADDR_WIDTH_G : natural := 23; -- memory address width
BEG_TEST_G : natural := 16#00_0000#; -- beginning test range address
END_TEST_G : natural := 16#7F_FFFF# -- ending test range address
);
port(
clk_i : in std_logic; -- master clock input
rst_i : in std_logic; -- reset
doAgain_i : in std_logic; -- re-do memory test
begun_i : in std_logic; -- memory operation begun_i indicator
done_i : in std_logic; -- memory operation done_i indicator
dIn_i : in std_logic_vector(DATA_WIDTH_G-1 downto 0); -- data from memory
rdPending_i : in std_logic; -- read operations in progress_o indicator
rd_o : out std_logic; -- memory read control signal
wr_o : out std_logic; -- memory write control signal
addr_o : out std_logic_vector(ADDR_WIDTH_G-1 downto 0); -- address to memory
dOut_o : out std_logic_vector(DATA_WIDTH_G-1 downto 0); -- data to memory
progress_o : out std_logic_vector(1 downto 0); -- memory test progress_o indicator
err_o : out std_logic -- memory error flag
);
end entity;
architecture arch of MemTest is
-- states of the memory tester state machine
type testState is (
INIT, -- init
LOAD, -- load memory with pseudo-random data
COMPARE, -- compare memory contents with pseudo-random data
EMPTY_PIPE, -- empty read pipeline
STOP -- stop and indicate memory status
);
signal state_r, state_x : testState := INIT; -- state register and next state
-- registers
signal addr_r, addr_x : unsigned(addr_o'range); -- address register
signal err_r, err_x : std_logic := NO; -- error flag
-- internal signals
signal ld : std_logic; -- load random number gen with seed value
signal cke : std_logic; -- clock-enable for random number gen
signal rand, rand1 : std_logic_vector(dOut_o'range); -- random number from generator
signal seed : std_logic_vector(dIn_i'range); -- random number starting seed
begin
seed <= (others => '1'); -- random number seed is 111...111
-- random number generator module
u0 : randGen
port map(
clk_i => clk_i, -- input clock
cke_i => cke, -- clock-enable to control when new random num is computed
ld_i => ld, -- load seed control signal
seed_i => seed, -- random number seed
rand_o => rand1 -- random number output from generator
);
rand <= rand1;
-- rand <= (others=>'0');
-- rand <= std_logic_vector(addr_r(15 downto 0));
-- rand <= std_logic_vector(TO_UNSIGNED(17,16));
-- connect internal registers to external busses
-- memory address bus driven by memory address register
addr_o <= std_logic_vector(addr_r); -- linear memory addressing
-- addr_o <= std_logic_vector(addr_r(1 downto 0) & addr_r(addr_o'high downto 2)); -- linear addressing simultaneously through each bank
dOut_o <= rand; -- always output the current random number to the memory
err_o <= err_r; -- output the current memory error status
-- memory test controller state machine operations
combinatorial : process(state_r, err_r, addr_r, dIn_i, rand, begun_i, done_i, rdPending_i, doAgain_i)
begin
-- default operations (do nothing unless explicitly stated in the following case statement)
rd_o <= NO; -- no memory write
wr_o <= NO; -- no memory read
ld <= NO; -- don't load the random number generator
cke <= NO; -- don't generate a new random number
addr_x <= addr_r; -- next address is the same as current address
err_x <= err_r; -- error flag is unchanged
state_x <= state_r; -- no change in memory tester state
-- **** compute the next state and operations ****
case state_r is
------------------------------------------------------
-- initialize the memory test controller
------------------------------------------------------
when INIT =>
ld <= YES; -- load random number seed
cke <= YES; -- enable clocking of rand num gen so seed gets loaded
addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- load starting mem address
err_x <= NO; -- clear memory error flag
state_x <= LOAD; -- next go to LOAD state and write pattern to memory
progress_o <= "00"; -- indicate the current controller state
when LOAD => -- load the memory with data from the random number generator
progress_o <= "01"; -- indicate the current controller state
if PIPE_EN_G then
wr_o <= YES;
if begun_i = YES then
if addr_r /= END_TEST_G then
addr_x <= addr_r + 1; -- so increment address
cke <= YES; -- and enable generator clock to get new random num
else
cke <= YES; -- enable generator clock and
ld <= YES; -- reload the generator with the seed value
addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- reset to start of test range
state_x <= COMPARE;
end if;
end if;
else
if done_i = NO then
wr_o <= YES;
elsif addr_r /= END_TEST_G then
addr_x <= addr_r + 1; -- so increment address
cke <= YES; -- and enable generator clock to get new random num
else
cke <= YES; -- enable generator clock and
ld <= YES; -- reload the generator with the seed value
addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- reset to start of test range
state_x <= COMPARE;
end if;
end if;
when COMPARE => -- re-run the generator and compare it to memory contents
progress_o <= "10"; -- indicate the current controller state
if PIPE_EN_G then
rd_o <= YES;
if begun_i = YES then
addr_x <= addr_r + 1; -- increment address to check next memory location
end if;
if addr_r = END_TEST_G then
state_x <= EMPTY_PIPE;
end if;
if done_i = YES then
if dIn_i /= rand then -- compare value from memory to random number
err_x <= YES; -- error if they don't match
end if;
cke <= YES; -- enable generator clock to get next random num
end if;
else
if done_i = NO then -- current read operation is not complete
rd_o <= YES; -- keep read signal active since memory read is not done_i
else -- current read operation is complete
if dIn_i /= rand then -- compare value from memory to random number
err_x <= YES; -- error if they don't match
end if;
if addr_r = END_TEST_G then
state_x <= STOP; -- go to STOP state once entire range has been checked
else
addr_x <= addr_r + 1; -- increment address to check next memory location
end if;
cke <= YES; -- and enable generator clock to get next random num
end if;
end if;
when EMPTY_PIPE =>
progress_o <= "10"; -- indicate the current controller state
if done_i = YES then
if dIn_i /= rand then -- compare value from memory to random number
err_x <= YES; -- error if they don't match
end if;
cke <= YES; -- enable generator clock to get next random num
end if;
if rdPending_i = NO then
state_x <= STOP;
addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- load starting mem address
end if;
when others => -- memory test is complete
progress_o <= "11"; -- indicate the current controller state
if doAgain_i = YES then
ld <= YES; -- load random number seed
cke <= YES; -- enable clocking of rand num gen so seed gets loaded
addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- load starting mem address
err_x <= NO; -- clear memory error flag
state_x <= INIT; -- go to the INIT state and and re-do memory test
end if;
end case;
end process;
-- update the registers of the memory tester controller
update : process(rst_i, clk_i)
begin
if rst_i = YES then
-- go to starting state and clear error flag when reset occurs
state_r <= INIT;
elsif rising_edge(clk_i) then
-- update error flag, address register, and state
err_r <= err_x;
addr_r <= addr_x;
state_r <= state_x;
end if;
end process;
end architecture;