Dual-Port Block RAM with Two Write Ports and Byte-wide Write Enable in Read-First Mode
2012-05-10 13:58
726 查看
Initializing Block RAM from external intel hex file 1 -- -- Dual-Port Block RAM with Two Write Ports and -- Byte-wide Write Enable in Read-First Mode -- -- Initializing Block RAM from external intel hex file -- -- http://www.keil.com/support/docs/1584/ -------------------------------------------------------------------- -- http://en.wikipedia.org/wiki/Intel_HEX -------------------------------------------------------------------- -- -- The format is a text file, with each line containing hexadecimal values -- encoding a sequence of data and their starting offset or absolute address. -- -- There are three types of Intel HEX: -- 8-bit, 16-bit, and 32-bit. They are distinguished by their byte order. -- -- Each line of Intel HEX file consists of six parts: -- -- Start code, one character, an ASCII colon ':'. -- -- Byte count, two hex digits, a number of bytes (hex digit pairs) in the data field. -- 16 (0x10) or 32 (0x20) bytes of data are the usual compromise values -- between line length and address overhead. -- -- Address, four hex digits, a 16-bit address of the beginning of the memory position for the data. -- Limited to 64 kilobytes, the limit is worked around by specifying higher bits via additional record types. -- This address is big endian. -- -- Record type, two hex digits, 00 to 05, defining the type of the data field. -- -- Data, a sequence of n bytes of the data themselves, represented by 2n hex digits. -- -- Checksum, two hex digits - the least significant byte of the two's complement -- of the sum of the values of all fields except fields 1 and 6 -- (Start code ":" byte and two hex digits of the Checksum). -- It is calculated by adding together the hex-encoded bytes (hex digit pairs), -- then leaving only the least significant byte of the result, -- and making a 2's complement (either by subtracting the byte from 0x100, -- or inverting it by XOR-ing with 0xFF and adding 0x01). -- If you are not working with 8-bit variables, -- you must suppress the overflow by AND-ing the result with 0xFF. -- The overflow may occur since both 0x100-0 and (0x00 XOR 0xFF)+1 equal 0x100. -- If the checksum is correctly calculated, adding all the bytes -- (the Byte count, both bytes in Address, the Record type, each Data byte and the Checksum) -- together will always result in a value wherein the least significant byte is zero (0x00). -- -- For example, on :0300300002337A1E -- 03 + 00 + 30 + 00 + 02 + 33 + 7A = E2, 2's complement is 1E -- -- There are six record types: -- 00, data record, contains data and 16-bit address. The format described above. -- -- 01, End Of File record. -- Must occur exactly once per file in the last line of the file. -- The byte count is 00 and the data field is empty. -- Usually the address field is also 0000, in which case the complete line is ':00000001FF'. -- Originally the End Of File record could contain a start address for the program being loaded, -- e.g. :00AB2F0125 would cause a jump to address AB2F. -- This was convenient when programs were loaded from punched paper tape. -- -- 02, Extended Segment Address Record, segment-base address (two hex digit pairs in big endian order). -- Used when 16 bits are not enough, identical to 80x86 real mode addressing. -- The address specified by the data field of the most recent 02 record is -- multiplied by 16 (shifted 4 bits left) and added to the subsequent 00 record addresses. -- This allows addressing of up to a megabyte of address space. -- The address field of this record has to be 0000, the byte count is 02 (the segment is 16-bit). -- The least significant hex digit of the segment address is always 0. -- -- 03, Start Segment Address Record. For 80x86 processors, it specifies the initial content of the CS:IP registers. -- The address field is 0000, the byte count is 04, -- the first two bytes are the CS value, the latter two are the IP value. -- -- 04, Extended Linear Address Record, allowing for fully 32 bit addressing (up to 4GiB). -- The address field is 0000, the byte count is 02. -- The two data bytes (two hex digit pairs in big endian order) represent -- the upper 16 bits of the 32 bit address for all subsequent 00 type records -- until the next 04 type record comes. -- If there is not a 04 type record, the upper 16 bits default to 0000. -- To get the absolute address for subsequent 00 type records, -- the address specified by the data field of the most recent 04 record is added to the 00 record addresses. -- -- 05, Start Linear Address Record. The address field is 0000, the byte count is 04. -- The 4 data bytes represent the 32-bit value loaded into the EIP register of the 80386 and higher CPU. -- -- :10 0100 00 214601360121470136007EFE09D21901 40 -- :10 0110 00 2146017EB7C20001FF5F160021480119 88 -- :10 0120 00 194E79234623965778239EDA3F01B2CA A7 -- :10 0130 00 3F0156702B5E712B722B732146013421 C7 -- :00 0000 01 FF -------------------------------------------------------------------- library ieee; use ieee.numeric_std.all; use ieee.std_logic_1164.all; use ieee.std_logic_textio.hread; use std.textio.all; entity dpram is generic ( HEX_FILE_NAME : string := "dpram.hex"; ADDR_WIDTH : natural := 13; -- 32K BYTE = 8K DWORD BYTE_WIDTH : natural := 8; -- always 8 BYTES : natural := 4); -- 1, 2, 4 port ( clk1 : in std_logic; en1 : in std_logic; we1 : in std_logic_vector (BYTES - 1 downto 0); addr1 : in std_logic_vector(ADDR_WIDTH - 1 downto 0); data_in1 : in std_logic_vector(BYTES*BYTE_WIDTH - 1 downto 0); data_out1 : out std_logic_vector(BYTES*BYTE_WIDTH-1 downto 0); clk2 : in std_logic; en2 : in std_logic; we2 : in std_logic_vector (BYTES - 1 downto 0); addr2 : in std_logic_vector(ADDR_WIDTH - 1 downto 0); data_in2 : in std_logic_vector(BYTES*BYTE_WIDTH - 1 downto 0); data_out2 : out std_logic_vector(BYTES*BYTE_WIDTH-1 downto 0)); end dpram; architecture rtl of dpram is type ram_array_type is array (2 ** ADDR_WIDTH-1 downto 0) of std_logic_vector (BYTES*BYTE_WIDTH-1 downto 0); type ram_byte_array_type is array (BYTES*(2 ** ADDR_WIDTH )-1 downto 0) of std_logic_vector (BYTE_WIDTH-1 downto 0); impure function ram_init_from_hex_file (constant hex_file_name : in string) return ram_array_type is file hex_file : text is in hex_file_name; variable ram_array : ram_array_type; variable ram_byte_array : ram_byte_array_type; variable line_buf : line; variable char : CHARACTER; variable rec_type : STD_LOGIC_VECTOR( 7 downto 0); variable byte : STD_LOGIC_VECTOR( 7 downto 0); variable count : STD_LOGIC_VECTOR( 7 downto 0); variable check : STD_LOGIC_VECTOR( 7 downto 0); variable addr : unsigned(15 downto 0); begin -- clear all bytes for i in 0 to BYTES*(2 ** ADDR_WIDTH )-1 loop ram_byte_array( i ) := ( others => '0' ); end loop; -- load from hex file while not endfile( hex_file ) loop -- read line readline(hex_file, line_buf); -- read ':' from line read(line_buf, char); if char /= ':' then next; end if; -- go to next loop -- read count from line hread(line_buf, count); -- read address from line hread(line_buf, byte); addr(15 downto 8) := unsigned( byte ); hread(line_buf, byte); addr( 7 downto 0) := unsigned( byte ); -- check recored type hread(line_buf, rec_type); if rec_type = "00000001" then exit; end if; -- it is an end of file record if rec_type = "00000000" then -- read bytes from line for i in 1 to to_integer( unsigned( count ) ) loop hread(line_buf, byte); ram_byte_array( to_integer( addr ) ) := byte; addr := addr + 1; end loop; end if; -- read checksum from line hread(line_buf, check); end loop; -- convert ram_byte_array to ram_array if BYTES = 4 then for i in 0 to 2 ** ADDR_WIDTH-1 loop ram_array( i ) := ram_byte_array( i * 4 + 3 ) & ram_byte_array( i * 4 + 2 ) & ram_byte_array( i * 4 + 1 ) & ram_byte_array( i * 4 + 0 ); end loop; elsif BYTES = 2 then for i in 0 to 2 ** ADDR_WIDTH-1 loop ram_array( i ) := ram_byte_array( i * 2 + 1 ) & ram_byte_array( i * 2 ) ; end loop; elsif BYTES = 1 then for i in 0 to 2 ** ADDR_WIDTH-1 loop ram_array( i ) := ram_byte_array( i ); end loop; end if; return ram_array; end function; shared variable ram : ram_array_type := ram_init_from_hex_file(HEX_FILE_NAME); attribute ram_style : string; attribute ram_style of ram : variable is "block"; type data_byte_array_type is array (BYTES-1 downto 0) of std_logic_vector (BYTE_WIDTH-1 downto 0); signal data_in1_byte_array : data_byte_array_type; signal data_in2_byte_array : data_byte_array_type; signal data_out1_byte_array : data_byte_array_type; signal data_out2_byte_array : data_byte_array_type; signal data_in1_pack : std_logic_vector (BYTES*BYTE_WIDTH-1 downto 0); signal data_in2_pack : std_logic_vector (BYTES*BYTE_WIDTH-1 downto 0); signal data_out1_pack : std_logic_vector (BYTES*BYTE_WIDTH-1 downto 0); signal data_out2_pack : std_logic_vector (BYTES*BYTE_WIDTH-1 downto 0); begin BYTES_1_generate : if BYTES = 1 generate data_in1_pack <= data_in1_byte_array(0); data_in2_pack <= data_in2_byte_array(0); data_out1_pack <= data_out1_byte_array(0); data_out2_pack <= data_out2_byte_array(0); end generate BYTES_1_generate; BYTES_2_generate : if BYTES = 2 generate data_in1_pack <= data_in1_byte_array(1) & data_in1_byte_array(0); data_in2_pack <= data_in2_byte_array(1) & data_in2_byte_array(0); data_out1_pack <= data_out1_byte_array(1) & data_out1_byte_array(0); data_out2_pack <= data_out2_byte_array(1) & data_out2_byte_array(0); end generate BYTES_2_generate; BYTES_4_generate : if BYTES = 4 generate data_in1_pack <= data_in1_byte_array(3) & data_in1_byte_array(2) & data_in1_byte_array(1) & data_in1_byte_array(0); data_in2_pack <= data_in2_byte_array(3) & data_in2_byte_array(2) & data_in2_byte_array(1) & data_in2_byte_array(0); data_out1_pack <= data_out1_byte_array(3) & data_out1_byte_array(2) & data_out1_byte_array(1) & data_out1_byte_array(0); data_out2_pack <= data_out2_byte_array(3) & data_out2_byte_array(2) & data_out2_byte_array(1) & data_out2_byte_array(0); end generate BYTES_4_generate; unpack : for i in 0 to BYTES - 1 generate data_out1_byte_array(i) <= ram( to_integer( unsigned( addr1 ) ) ) ( (i+1)*BYTE_WIDTH-1 downto i*BYTE_WIDTH ) ; data_out2_byte_array(i) <= ram( to_integer( unsigned( addr2 ) ) ) ( (i+1)*BYTE_WIDTH-1 downto i*BYTE_WIDTH ) ; process( we1(i), data_in1, addr1 ) begin if we1(i) = '1' then data_in1_byte_array(i) <= data_in1((i+1)*BYTE_WIDTH-1 downto i*BYTE_WIDTH ); else data_in1_byte_array(i) <= ram( to_integer( unsigned( addr1 ) ) ) ( (i+1)*BYTE_WIDTH-1 downto i*BYTE_WIDTH ) ; end if; end process; process( we2(i), data_in2, addr2 ) begin if we2(i) = '1' then data_in2_byte_array(i) <= data_in2((i+1)*BYTE_WIDTH-1 downto i*BYTE_WIDTH ); else data_in2_byte_array(i) <= ram( to_integer( unsigned( addr2 ) ) ) ( (i+1)*BYTE_WIDTH-1 downto i*BYTE_WIDTH ) ; end if; end process; end generate unpack; process(clk1) begin if(rising_edge(clk1)) then if(en1 = '1') then ram( to_integer( unsigned( addr1 ) ) ) := data_in1_pack; data_out1 <= data_out1_pack; end if; end if; end process; process(clk2) begin if(rising_edge(clk2)) then if(en2 = '1') then ram( to_integer( unsigned( addr2 ) ) ) := data_in2_pack; data_out2 <= data_out2_pack; end if; end if; end process; end rtl;
相关文章推荐
- Dual port RAM with enable on each port( vhdl )
- Read a Text File with VBA in Excel, and Write the Text to a Spreadsheet
- Read and write SD cards in a raw way with dd
- How to mount partition with ntfs file system and read write access
- How To Write, Deploy, and Interact with Ethereum Smart Contracts on a Private Blockchain
- (转载)XML Tutorial for iOS: How To Read and Write XML Documents with GDataXML
- Sample: Write And Read data from HDFS with java API
- write and read mtd device(轉載自http://stackoverflow.com/questions/15336285/write-on-a-mtd-block-devic)
- How To Read and Write XML Documents with GDataXML
- 8155/8156 2048-bit static MOS RAM with I/O ports and timer
- Read and Write to a Keyboard device in Linux using C++
- How To Read and Write XML Documents with GDataXML
- How to read and write JSON files in Java(Gson)
- How to mount partition with ntfs file system and read write access
- Setup Apache2 in Debian 9 and enable two ports for two sites
- How To Read and Write XML Documents with GDataXML(使用GData读写XML文档)
- week 3th、run and write CLI case in CAFE with Simulator
- read and write in C
- Read and Write files IN PHP
- How To Read and Write BLOB Data by Using ADO.NET with Visual C# .NET