www.pudn.com > jaguar2s.zip > lpm_ram_dp.vhd


library IEEE; 
use IEEE.std_logic_1164.all; 
use IEEE.std_logic_arith.all; 
use IEEE.std_logic_unsigned.all; 
--use work.LPM_COMPONENTS.all; 
use std.textio.all; 
 
entity LPM_RAM_DP is 
    generic ( 
        LPM_WIDTH             : natural;    -- MUST be greater than 0 
        LPM_WIDTHAD           : natural;    -- MUST be greater than 0 
        LPM_NUMWORDS          : natural := 0; 
        LPM_INDATA            : string := "REGISTERED"; 
        LPM_OUTDATA           : string := "REGISTERED"; 
        LPM_RDADDRESS_CONTROL : string := "REGISTERED"; 
        LPM_WRADDRESS_CONTROL : string := "REGISTERED"; 
        LPM_FILE              : string := "UNUSED"; 
        LPM_TYPE              : string := "LPM_RAM_DP"; 
        LPM_HINT              : string := "UNUSED" 
     ); 
     port ( 
        RDCLOCK     : in std_logic := '0'; 
        RDCLKEN     : in std_logic := '1'; 
        RDADDRESS   : in std_logic_vector(LPM_WIDTHAD-1 downto 0); 
        RDEN        : in std_logic := '1'; 
        DATA        : in std_logic_vector(LPM_WIDTH-1 downto 0); 
        WRADDRESS   : in std_logic_vector(LPM_WIDTHAD-1 downto 0); 
        WREN        : in std_logic; 
        WRCLOCK     : in std_logic := '0'; 
        WRCLKEN     : in std_logic := '1'; 
        Q           : out std_logic_vector(LPM_WIDTH-1 downto 0) 
     ); 
 
        function int_to_str( value : integer ) return string is 
        variable ivalue,index : integer; 
        variable digit : integer; 
        variable line_no: string(8 downto 1) := "        ";   
        begin 
                ivalue := value; 
                index := 1; 
                while (ivalue > 0) loop 
                        digit := ivalue MOD 10; 
                        ivalue := ivalue/10; 
                        case digit is 
                                when 0 => 
                                        line_no(index) := '0'; 
                                when 1 => 
                                        line_no(index) := '1'; 
                                when 2 => 
                                        line_no(index) := '2'; 
                                when 3 => 
                                        line_no(index) := '3'; 
                                when 4 => 
                                        line_no(index) := '4'; 
                                when 5 => 
                                        line_no(index) := '5'; 
                                when 6 => 
                                        line_no(index) := '6'; 
                                when 7 => 
                                        line_no(index) := '7'; 
                                when 8 => 
                                        line_no(index) := '8'; 
                                when 9 => 
                                        line_no(index) := '9'; 
                                when others => 
                                        ASSERT FALSE 
                                        REPORT "Illegal number!" 
                                        SEVERITY ERROR; 
                        end case; 
                        index := index + 1; 
                end loop; 
                return line_no; 
        end; 
 
        function hex_str_to_int( str : string ) return integer is 
        variable len : integer := str'length; 
        variable ivalue : integer := 0; 
        variable digit : integer; 
        begin 
                for i in len downto 1 loop 
                        case str(i) is 
                                when '0' => 
                                        digit := 0; 
                                when '1' => 
                                        digit := 1; 
                                when '2' => 
                                        digit := 2; 
                                when '3' => 
                                        digit := 3; 
                                when '4' => 
                                        digit := 4; 
                                when '5' => 
                                        digit := 5; 
                                when '6' => 
                                        digit := 6; 
                                when '7' => 
                                        digit := 7; 
                                when '8' => 
                                        digit := 8; 
                                when '9' => 
                                        digit := 9; 
                                when 'A' => 
                                        digit := 10; 
                                when 'a' => 
                                        digit := 10; 
                                when 'B' => 
                                        digit := 11; 
                                when 'b' => 
                                        digit := 11; 
                                when 'C' => 
                                        digit := 12; 
                                when 'c' => 
                                        digit := 12; 
                                when 'D' => 
                                        digit := 13; 
                                when 'd' => 
                                        digit := 13; 
                                when 'E' => 
                                        digit := 14; 
                                when 'e' => 
                                        digit := 14; 
                                when 'F' => 
                                        digit := 15; 
                                when 'f' => 
                                        digit := 15; 
                                when others => 
                                        ASSERT FALSE 
                                        REPORT "Illegal character "&  str(i) & "in Intel Hex File! " 
                                        SEVERITY ERROR; 
                        end case; 
                        ivalue := ivalue * 16 + digit; 
                end loop; 
                return ivalue; 
        end; 
 
        procedure Shrink_line(L : inout LINE; pos : in integer) is 
        subtype nstring is string(1 to pos); 
        variable stmp : nstring; 
        begin 
                if pos >= 1 then 
                        read(l, stmp); 
                end if; 
        end; 
 
end LPM_RAM_DP; 
 
architecture LPM_SYN of lpm_ram_dp is 
 
--type lpm_memory is array(lpm_numwords-1 downto 0) of std_logic_vector(lpm_width-1 downto 0); 
type lpm_memory is array((2**lpm_widthad)-1 downto 0) of std_logic_vector(lpm_width-1 downto 0); 
 
signal data_tmp, data_reg : std_logic_vector(lpm_width-1 downto 0); 
signal q_tmp, q_reg : std_logic_vector(lpm_width-1 downto 0) := (others => '0'); 
signal rdaddress_tmp, rdaddress_reg : std_logic_vector(lpm_widthad-1 downto 0); 
signal wraddress_tmp, wraddress_reg : std_logic_vector(lpm_widthad-1 downto 0); 
signal wren_tmp, wren_reg : std_logic; 
signal rden_tmp, rden_reg : std_logic; 
 
begin 
        sync: process(data, data_reg, rden, rden_reg, rdaddress, rdaddress_reg, 
                      wren, wren_reg, wraddress, wraddress_reg, q_tmp, q_reg) 
        begin 
            if (lpm_rdaddress_control = "REGISTERED") then 
                  rdaddress_tmp <= rdaddress_reg; 
                  rden_tmp <= rden_reg; 
            elsif (lpm_rdaddress_control = "UNREGISTERED") then 
                  rdaddress_tmp <= rdaddress; 
                  rden_tmp <= rden; 
            else 
                  ASSERT FALSE 
                  REPORT "Illegal LPM_RDADDRESS_CONTROL property value for LPM_RAM_DP!" 
                  SEVERITY ERROR; 
            end if; 
            if (lpm_wraddress_control = "REGISTERED") then 
                  wraddress_tmp <= wraddress_reg; 
                  wren_tmp <= wren_reg;  
            elsif (lpm_wraddress_control = "UNREGISTERED") then 
                  wraddress_tmp <= wraddress; 
                  wren_tmp <= wren; 
            else 
                  ASSERT FALSE 
                  REPORT "Illegal LPM_WRADDRESS_CONTROL property value for LPM_RAM_DP!" 
                  SEVERITY ERROR; 
            end if; 
            if (lpm_indata = "REGISTERED") then 
                  data_tmp <= data_reg; 
            elsif (lpm_indata = "UNREGISTERED") then 
                  data_tmp <= data; 
            else 
                  ASSERT FALSE 
                  REPORT "Illegal LPM_INDATA property value for LPM_RAM_DP!" 
                  SEVERITY ERROR; 
            end if; 
            if (lpm_outdata = "REGISTERED") then 
                 q <= q_reg; 
            elsif (lpm_outdata = "UNREGISTERED") then 
                 q <= q_tmp; 
            else 
                 ASSERT FALSE 
                 REPORT "Illegal LPM_OUTDATA property value for LPM_RAM_DP!" 
                 SEVERITY ERROR; 
            end if; 
        end process; 
 
        input_reg: process (wrclock) 
        begin 
            if wrclock'event and wrclock = '1' and wrclken = '1' then 
                  data_reg <= data; 
                  wraddress_reg <= wraddress; 
                  wren_reg <= wren; 
            end if; 
        end process; 
 
        output_reg: process (rdclock) 
        begin 
            if rdclock'event and rdclock = '1' and rdclken = '1' then 
                  rdaddress_reg <= rdaddress; 
                  rden_reg <= rden;  
                  q_reg <= q_tmp; 
            end if; 
        end process; 
 
        memory: process(data_tmp, wren_tmp, rdaddress_tmp, wraddress_tmp, rden_tmp) 
        variable mem_data : lpm_memory; 
        variable mem_data_tmp : integer := 0; 
        variable mem_init: boolean := false; 
        variable i,j,k,lineno: integer := 0; 
        variable buf: line ; 
        variable booval: boolean ; 
        FILE unused_file: TEXT IS OUT "UNUSED"; 
        FILE mem_data_file: TEXT IS IN LPM_FILE; 
        variable base, byte, rec_type, datain, addr, checksum: string(2 downto 1); 
        variable startadd: string(4 downto 1); 
        variable ibase: integer := 0; 
        variable ibyte: integer := 0; 
        variable istartadd: integer := 0; 
        variable check_sum_vec, check_sum_vec_tmp: std_logic_vector(7 downto 0); 
        begin 
            -- INITIALIZE -- 
            if NOT(mem_init) then 
                 -- INITIALIZE TO 0 -- 
                 for i in mem_data'LOW to mem_data'HIGH loop 
                      mem_data(i) := (OTHERS => '0'); 
                 end loop; 
 
                 if (LPM_FILE = "UNUSED") then 
                      ASSERT FALSE 
                      REPORT "Initialization file not found!" 
                      SEVERITY WARNING; 
                 else 
                      WHILE NOT ENDFILE(mem_data_file) loop 
                          booval := true; 
                          READLINE(mem_data_file, buf); 
                          lineno := lineno + 1; 
                          check_sum_vec := (OTHERS => '0'); 
                          if (buf(buf'LOW) = ':') then 
                              i := 1; 
                              shrink_line(buf, i); 
                              READ(L=>buf, VALUE=>byte, good=>booval); 
                              if not (booval) then 
                                  ASSERT FALSE 
                                  REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format!" 
                                  SEVERITY ERROR; 
                              end if; 
                              ibyte := hex_str_to_int(byte); 
                              check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(ibyte, 8)); 
                              READ(L=>buf, VALUE=>startadd, good=>booval); 
                              if not (booval) then 
                                  ASSERT FALSE 
                                  REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " 
                                  SEVERITY ERROR; 
                              end if; 
                              istartadd := hex_str_to_int(startadd); 
                              addr(2) := startadd(4); 
                              addr(1) := startadd(3); 
                              check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(hex_str_to_int(addr), 8)); 
                              addr(2) := startadd(2); 
                              addr(1) := startadd(1); 
                              check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(hex_str_to_int(addr), 8)); 
                              READ(L=>buf, VALUE=>rec_type, good=>booval); 
                              if not (booval) then 
                                   ASSERT FALSE 
                                   REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " 
                                   SEVERITY ERROR; 
                              end if; 
                              check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(hex_str_to_int(rec_type), 8)); 
                          else 
                              ASSERT FALSE 
                              REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " 
                              SEVERITY ERROR; 
                          end if; 
                          case rec_type is 
                              when "00"=>     -- Data record 
                                   i := 0; 
                                   k := lpm_width / 8; 
                                   if ((lpm_width MOD 8) /= 0) then 
                                        k := k + 1;  
                                   end if; 
                                   -- k = no. of bytes per CAM entry. 
                                   while (i < ibyte) loop 
                                        mem_data_tmp := 0; 
                                        for j in 1 to k loop 
                                             READ(L=>buf, VALUE=>datain,good=>booval); -- read in data a byte (2 hex chars) at a time. 
                                             if not (booval) then 
                                                 ASSERT FALSE 
                                                 REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " 
                                                 SEVERITY ERROR; 
                                             end if; 
                                             check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(hex_str_to_int(datain), 8)); 
                                             mem_data_tmp := mem_data_tmp * 256 + hex_str_to_int(datain); 
                                        end loop; 
                                        i := i + k; 
                                        mem_data(ibase + istartadd) := CONV_STD_LOGIC_VECTOR(mem_data_tmp, lpm_width); 
                                        istartadd := istartadd + 1; 
                                    end loop; 
                               when "01"=> 
                                    exit; 
                               when "02"=> 
                                     ibase := 0; 
                                     if (ibyte /= 2) then 
                                          ASSERT FALSE 
                                          REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format for record type 02! " 
                                          SEVERITY ERROR; 
                                     end if; 
                                     for i in 0 to (ibyte-1) loop 
                                          READ(L=>buf, VALUE=>base,good=>booval); 
                                          ibase := ibase * 256 + hex_str_to_int(base); 
                                          if not (booval) then 
                                              ASSERT FALSE 
                                              REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " 
                                              SEVERITY ERROR; 
                                          end if; 
                                          check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(hex_str_to_int(base), 8)); 
                                      end loop; 
                                      ibase := ibase * 16; 
                                 when OTHERS => 
                                      ASSERT FALSE 
                                      REPORT "[Line "& int_to_str(lineno) & "]:Illegal record type in Intel Hex File! " 
                                      SEVERITY ERROR; 
                             end case; 
                             READ(L=>buf, VALUE=>checksum,good=>booval); 
                             if not (booval) then 
                                  ASSERT FALSE 
                                  REPORT "[Line "& int_to_str(lineno) & "]:Checksum is missing! " 
                                  SEVERITY ERROR; 
                             end if; 
 
                             check_sum_vec := unsigned(not (check_sum_vec)) + 1 ; 
                             check_sum_vec_tmp := CONV_STD_LOGIC_VECTOR(hex_str_to_int(checksum),8); 
 
                             if (unsigned(check_sum_vec) /= unsigned(check_sum_vec_tmp)) then 
                                  ASSERT FALSE 
                                  REPORT "[Line "& int_to_str(lineno) & "]:Incorrect checksum!" 
                                  SEVERITY ERROR; 
                             end if; 
                         end loop; 
                     end if; 
                     mem_init := TRUE; 
                end if; 
 
                -- MEMORY FUNCTION -- 
                if wren_tmp = '1' then 
                     mem_data (conv_integer(wraddress_tmp)) := data_tmp; 
                end if; 
                if rden_tmp = '1' then 
                     q_tmp <= mem_data(conv_integer(rdaddress_tmp)); 
                --else 
                --    q_tmp <= (OTHERS => 'Z'); 
                end if; 
        end process; 
 
end LPM_SYN;