Initializing Block RAM from external intel hex file 1 --
2 -- Dual-Port Block RAM
with Two Write Ports
and
3 -- Byte-wide Write Enable
in Read-
First Mode
4 --
5 -- Initializing Block RAM from external intel hex
file
6 --
7 -- http:
//www.keil.com/support/docs/1584/
8 --------------------------------------------------------------------
9 -- http:
//en.wikipedia.org/wiki/Intel_HEX
10 --------------------------------------------------------------------
11 --
12 -- The format
is a
text file,
with each
line containing hexadecimal values
13 -- encoding a sequence
of data
and their starting offset
or absolute address.
14 --
15 -- There are three types
of Intel HEX:
16 --
8-
bit,
16-
bit,
and 32-
bit. They are distinguished by their
byte order.
17 --
18 -- Each
line of Intel HEX
file consists
of six parts:
19 --
20 -- Start code, one
character, an ASCII colon
':'.
21 --
22 -- Byte count, two hex digits, a number
of bytes (hex digit pairs)
in the data field.
23 --
16 (
0x10)
or 32 (
0x20) bytes
of data are the usual compromise values
24 -- between
line length
and address overhead.
25 --
26 -- Address, four hex digits, a
16-
bit address
of the beginning
of the memory position
for the data.
27 -- Limited
to 64 kilobytes, the limit
is worked around by specifying higher bits via additional
record types.
28 -- This address
is big endian.
29 --
30 -- Record
type, two hex digits,
00 to 05, defining the
type of the data field.
31 --
32 -- Data, a sequence
of n bytes
of the data themselves, represented by 2n hex digits.
33 --
34 -- Checksum, two hex digits - the least significant
byte of the two
's complement
35 --
of the sum
of the values
of all fields except fields
1 and 6
36 -- (Start code
":" byte and two hex digits
of the Checksum).
37 -- It
is calculated by adding together the hex-
encoded bytes (hex digit pairs),
38 --
then leaving only the least significant
byte of the result,
39 --
and making a
2's complement (either by subtracting the byte from 0x100,
40 --
or inverting it by
XOR-ing
with 0xFF and adding
0x01).
41 -- If you are
not working
with 8-
bit variables,
42 -- you must suppress the overflow by
AND-ing the result
with 0xFF.
43 -- The overflow may occur since both
0x100-
0 and (
0x00 XOR 0xFF)+
1 equal
0x100.
44 -- If the checksum
is correctly calculated, adding
all the bytes
45 -- (the Byte count, both bytes
in Address, the Record
type, each Data
byte and the Checksum)
46 -- together will always result
in a value wherein the least significant
byte is zero (
0x00).
47 --
48 -- For example,
on :0300300002337A1E
49 --
03 +
00 +
30 +
00 +
02 +
33 + 7A = E2,
2's complement is 1E
50 --
51 -- There are six
record types:
52 --
00, data
record, contains data
and 16-
bit address. The format described above.
53 --
54 --
01, End Of File
record.
55 -- Must occur exactly once per
file in the last
line of the
file.
56 -- The
byte count
is 00 and the data field
is empty.
57 -- Usually the address field
is also
0000,
in which
case the complete
line is ':00000001FF'.
58 -- Originally the End Of File
record could contain a start address
for the program being loaded,
59 -- e.g. :00AB2F0125 would cause a jump
to address AB2F.
60 -- This was convenient
when programs were loaded from punched paper tape.
61 --
62 --
02, Extended Segment Address Record, segment-base address (two hex digit pairs
in big endian order).
63 -- Used
when 16 bits are
not enough, identical
to 8
0x86 real mode addressing.
64 -- The address specified by the data field
of the most recent
02 record is
65 -- multiplied by
16 (shifted
4 bits
left)
and added
to the subsequent
00 record addresses.
66 -- This allows addressing
of up
to a megabyte
of address space.
67 -- The address field
of this
record has
to be
0000, the
byte count
is 02 (the segment
is 16-
bit).
68 -- The least significant hex digit
of the segment address
is always
0.
69 --
70 --
03, Start Segment Address Record. For 8
0x86 processors, it specifies the initial content
of the CS:IP registers.
71 -- The address field
is 0000, the
byte count
is 04,
72 --
the first two bytes are the CS value, the latter two are the IP value.
73 --
74 --
04, Extended Linear Address Record, allowing
for fully
32 bit addressing (up
to 4GiB).
75 -- The address field
is 0000, the
byte count
is 02.
76 -- The two data bytes (two hex digit pairs
in big endian order) represent
77 -- the upper
16 bits
of the
32 bit address
for all subsequent
00 type records
78 --
until the
next 04 type record comes.
79 -- If there
is not a
04 type record, the upper
16 bits default
to 0000.
80 -- To get the absolute address
for subsequent
00 type records,
81 -- the address specified by the data field
of the most recent
04 record is added
to the
00 record addresses.
82 --
83 --
05, Start Linear Address Record. The address field
is 0000, the
byte count
is 04.
84 -- The
4 data bytes represent the
32-
bit value loaded into the EIP
register of the
80386 and higher CPU.
85
86 --
87 -- :
10 0100 00 214601360121470136007EFE09D21901
40
88 -- :
10 0110 00 2146017EB7C20001FF5F160021480119
88
89 -- :
10 0120 00 194E79234623965778239EDA3F01B2CA A7
90 -- :
10 0130 00 3F0156702B5E712B722B732146013421 C7
91 -- :
00 0000 01 FF
92 --------------------------------------------------------------------
93
94 library ieee;
95 use ieee.numeric_std.
all;
96 use ieee.std_logic_1164.
all;
97 use ieee.std_logic_textio.hread;
98 use std.
textio.
all;
99
100 entity dpram
is
101
102 generic (
103 HEX_FILE_NAME :
string :=
"dpram.hex";
104 ADDR_WIDTH : natural :=
13; -- 32K BYTE =
8K DWORD
105 BYTE_WIDTH : natural :=
8; -- always
8
106 BYTES : natural :=
4); --
1,
2,
4
107
108 port (
109 clk1 :
in std_logic;
110 en1 :
in std_logic;
111 we1 :
in std_logic_vector (BYTES -
1 downto 0);
112 addr1 :
in std_logic_vector(ADDR_WIDTH -
1 downto 0);
113 data_in1 :
in std_logic_vector(BYTES*BYTE_WIDTH -
1 downto 0);
114 data_out1 :
out std_logic_vector(BYTES*BYTE_WIDTH-
1 downto 0);
115 clk2 :
in std_logic;
116 en2 :
in std_logic;
117 we2 :
in std_logic_vector (BYTES -
1 downto 0);
118 addr2 :
in std_logic_vector(ADDR_WIDTH -
1 downto 0);
119 data_in2 :
in std_logic_vector(BYTES*BYTE_WIDTH -
1 downto 0);
120 data_out2 :
out std_logic_vector(BYTES*BYTE_WIDTH-
1 downto 0));
121
122 end dpram;
123
124 architecture rtl
of dpram
is
125 type ram_array_type
is array (
2 ** ADDR_WIDTH-
1 downto 0)
of std_logic_vector (BYTES*BYTE_WIDTH-
1 downto 0);
126 type ram_byte_array_type
is array (BYTES*(
2 ** ADDR_WIDTH )-
1 downto 0)
of std_logic_vector (BYTE_WIDTH-
1 downto 0);
127
128 impure function ram_init_from_hex_file (
constant hex_file_name :
in string)
return ram_array_type
is
129 file hex_file :
text is in hex_file_name;
130 variable ram_array : ram_array_type;
131 variable ram_byte_array : ram_byte_array_type;
132 variable line_buf :
line;
133 variable char :
CHARACTER;
134 variable rec_type :
STD_LOGIC_VECTOR(
7 downto 0);
135 variable byte :
STD_LOGIC_VECTOR(
7 downto 0);
136 variable count :
STD_LOGIC_VECTOR(
7 downto 0);
137 variable check :
STD_LOGIC_VECTOR(
7 downto 0);
138 variable addr : unsigned(
15 downto 0);
139 begin
140 -- clear
all bytes
141 for i
in 0 to BYTES*(
2 ** ADDR_WIDTH )-
1 loop
142 ram_byte_array( i ) := (
others =>
'0' );
143 end loop;
144
145 -- load from hex
file
146 while not endfile( hex_file )
loop
147 --
read line
148 readline(hex_file, line_buf);
149
150 --
read ':' from
line
151 read(line_buf,
char);
152 if char /=
':' then next;
end if; -- go
to next loop
153 --
read count from
line
154 hread(line_buf, count);
155 --
read address from
line
156 hread(line_buf,
byte); addr(
15 downto 8) := unsigned(
byte );
157 hread(line_buf,
byte); addr(
7 downto 0) := unsigned(
byte );
158
159 -- check recored
type
160 hread(line_buf, rec_type);
161 if rec_type =
"00000001" then exit;
end if; -- it
is an
end of file record
162
163 if rec_type =
"00000000" then
164 --
read bytes from
line
165 for i
in 1 to to_integer( unsigned( count ) )
loop
166 hread(line_buf,
byte);
167 ram_byte_array( to_integer( addr ) ) :=
byte;
168
169 addr := addr +
1;
170 end loop;
171 end if;
172
173 --
read checksum from
line
174 hread(line_buf, check);
175 end loop;
176
177 -- convert ram_byte_array
to ram_array
178 if BYTES =
4 then
179 for i
in 0 to 2 ** ADDR_WIDTH-
1 loop
180 ram_array( i ) := ram_byte_array( i *
4 +
3 )
181 & ram_byte_array( i *
4 +
2 )
182 & ram_byte_array( i *
4 +
1 )
183 & ram_byte_array( i *
4 +
0 );
184 end loop;
185
186 elsif BYTES =
2 then
187 for i
in 0 to 2 ** ADDR_WIDTH-
1 loop
188 ram_array( i ) := ram_byte_array( i *
2 +
1 )
189 & ram_byte_array( i *
2 ) ;
190 end loop;
191
192 elsif BYTES =
1 then
193 for i
in 0 to 2 ** ADDR_WIDTH-
1 loop
194 ram_array( i ) :=
ram_byte_array( i );
195 end loop;
196
197 end if;
198
199 return ram_array;
200 end function;
201
202
203 shared variable ram : ram_array_type :=
ram_init_from_hex_file(HEX_FILE_NAME);
204 attribute ram_style :
string;
205 attribute ram_style
of ram :
variable is "block";
206
207 type data_byte_array_type
is array (BYTES-
1 downto 0)
of std_logic_vector (BYTE_WIDTH-
1 downto 0);
208 signal data_in1_byte_array : data_byte_array_type;
209 signal data_in2_byte_array : data_byte_array_type;
210 signal data_out1_byte_array : data_byte_array_type;
211 signal data_out2_byte_array : data_byte_array_type;
212
213 signal data_in1_pack :
std_logic_vector (BYTES*BYTE_WIDTH-
1 downto 0);
214 signal data_in2_pack :
std_logic_vector (BYTES*BYTE_WIDTH-
1 downto 0);
215 signal data_out1_pack :
std_logic_vector (BYTES*BYTE_WIDTH-
1 downto 0);
216 signal data_out2_pack :
std_logic_vector (BYTES*BYTE_WIDTH-
1 downto 0);
217
218 begin
219 BYTES_1_generate :
if BYTES =
1 generate
220 data_in1_pack <= data_in1_byte_array(
0);
221 data_in2_pack <= data_in2_byte_array(
0);
222 data_out1_pack <= data_out1_byte_array(
0);
223 data_out2_pack <= data_out2_byte_array(
0);
224 end generate BYTES_1_generate;
225
226 BYTES_2_generate :
if BYTES =
2 generate
227 data_in1_pack <= data_in1_byte_array(
1) & data_in1_byte_array(
0);
228 data_in2_pack <= data_in2_byte_array(
1) & data_in2_byte_array(
0);
229 data_out1_pack <= data_out1_byte_array(
1) & data_out1_byte_array(
0);
230 data_out2_pack <= data_out2_byte_array(
1) & data_out2_byte_array(
0);
231 end generate BYTES_2_generate;
232
233 BYTES_4_generate :
if BYTES =
4 generate
234 data_in1_pack <= data_in1_byte_array(
3) & data_in1_byte_array(
2) & data_in1_byte_array(
1) & data_in1_byte_array(
0);
235 data_in2_pack <= data_in2_byte_array(
3) & data_in2_byte_array(
2) & data_in2_byte_array(
1) & data_in2_byte_array(
0);
236 data_out1_pack <= data_out1_byte_array(
3) & data_out1_byte_array(
2) & data_out1_byte_array(
1) & data_out1_byte_array(
0);
237 data_out2_pack <= data_out2_byte_array(
3) & data_out2_byte_array(
2) & data_out2_byte_array(
1) & data_out2_byte_array(
0);
238 end generate BYTES_4_generate;
239
240 unpack :
for i
in 0 to BYTES -
1 generate
241 data_out1_byte_array(i) <= ram( to_integer( unsigned( addr1 ) ) ) ( (i+
1)*BYTE_WIDTH-
1 downto i*
BYTE_WIDTH ) ;
242 data_out2_byte_array(i) <= ram( to_integer( unsigned( addr2 ) ) ) ( (i+
1)*BYTE_WIDTH-
1 downto i*
BYTE_WIDTH ) ;
243
244 process( we1(i), data_in1, addr1 )
245 begin
246 if we1(i) =
'1' then
247 data_in1_byte_array(i) <= data_in1((i+
1)*BYTE_WIDTH-
1 downto i*
BYTE_WIDTH );
248 else
249 data_in1_byte_array(i) <= ram( to_integer( unsigned( addr1 ) ) ) ( (i+
1)*BYTE_WIDTH-
1 downto i*
BYTE_WIDTH ) ;
250 end if;
251 end process;
252
253 process( we2(i), data_in2, addr2 )
254 begin
255 if we2(i) =
'1' then
256 data_in2_byte_array(i) <= data_in2((i+
1)*BYTE_WIDTH-
1 downto i*
BYTE_WIDTH );
257 else
258 data_in2_byte_array(i) <= ram( to_integer( unsigned( addr2 ) ) ) ( (i+
1)*BYTE_WIDTH-
1 downto i*
BYTE_WIDTH ) ;
259 end if;
260 end process;
261
262 end generate unpack;
263
264 process(clk1)
265 begin
266 if(
rising_edge(clk1))
then
267 if(en1 =
'1')
then
268 ram( to_integer( unsigned( addr1 ) ) ) :=
data_in1_pack;
269 data_out1 <=
data_out1_pack;
270 end if;
271 end if;
272 end process;
273
274 process(clk2)
275 begin
276 if(
rising_edge(clk2))
then
277 if(en2 =
'1')
then
278 ram( to_integer( unsigned( addr2 ) ) ) :=
data_in2_pack;
279 data_out2 <=
data_out2_pack;
280 end if;
281 end if;
282 end process;
283
284 end rtl;
转载于:https://www.cnblogs.com/shangdawei/archive/2012/05/10/2494236.html