1library ieee; 2use ieee.std_logic_1164.all, 3 ieee.numeric_std.all; 4 5entity tdp_ram is 6 generic ( 7 ADDRWIDTH_A : positive := 12; 8 WIDTH_A : positive := 8; 9 10 ADDRWIDTH_B : positive := 10; 11 WIDTH_B : positive := 32; 12 13 COL_WIDTH : positive := 8 14 ); 15 port ( 16 clk_a : in std_logic; 17 read_a : in std_logic; 18 write_a : in std_logic; 19 byteen_a : in std_logic_vector(WIDTH_A/COL_WIDTH - 1 downto 0); 20 addr_a : in std_logic_vector(ADDRWIDTH_A - 1 downto 0); 21 data_read_a : out std_logic_vector(WIDTH_A - 1 downto 0); 22 data_write_a : in std_logic_vector(WIDTH_A - 1 downto 0); 23 24 clk_b : in std_logic; 25 read_b : in std_logic; 26 write_b : in std_logic; 27 byteen_b : in std_logic_vector(WIDTH_B/COL_WIDTH - 1 downto 0); 28 addr_b : in std_logic_vector(ADDRWIDTH_B - 1 downto 0); 29 data_read_b : out std_logic_vector(WIDTH_B - 1 downto 0); 30 data_write_b : in std_logic_vector(WIDTH_B - 1 downto 0) 31 ); 32end tdp_ram; 33 34architecture behavioral of tdp_ram is 35 function log2(val : INTEGER) return natural is 36 variable res : natural; 37 begin 38 for i in 0 to 31 loop 39 if (val <= (2 ** i)) then 40 res := i; 41 exit; 42 end if; 43 end loop; 44 45 return res; 46 end function log2; 47 48 function eq_assert(x : integer; y : integer) return integer is 49 begin 50 assert x = y; 51 return x; 52 end function eq_assert; 53 54 constant COLS_A : positive := WIDTH_A / COL_WIDTH; 55 constant COLS_B : positive := WIDTH_B / COL_WIDTH; 56 57 constant TOTAL_COLS : positive := eq_assert(COLS_A * 2 ** ADDRWIDTH_A, COLS_B * 2 ** ADDRWIDTH_B); 58 59 constant EXTRA_ADDR_BITS_A : natural := log2(COLS_A); 60 constant EXTRA_ADDR_BITS_B : natural := log2(COLS_B); 61 62 type ram_t is array(0 to TOTAL_COLS - 1) of std_logic_vector(COL_WIDTH - 1 downto 0); 63 shared variable store : ram_t := (others => (others => '0')); 64 65 signal reg_a : std_logic_vector(WIDTH_A - 1 downto 0); 66 signal reg_b : std_logic_vector(WIDTH_B - 1 downto 0); 67begin 68 assert WIDTH_A mod COL_WIDTH = 0 and 69 WIDTH_B mod COL_WIDTH = 0 and 70 2 ** (ADDRWIDTH_A + EXTRA_ADDR_BITS_A) = TOTAL_COLS and 71 2 ** (ADDRWIDTH_B + EXTRA_ADDR_BITS_B) = TOTAL_COLS 72 report "Both WIDTH_A and WIDTH_B have to be a power-of-two multiple of COL_WIDTH" 73 severity failure; 74 75 process(clk_a) 76 begin 77 if rising_edge(clk_a) then 78 for i in 0 to COLS_A - 1 loop 79 if write_a = '1' and byteen_a(i) = '1' then 80 store(to_integer(unsigned(addr_a) & to_unsigned(i, EXTRA_ADDR_BITS_A))) := 81 data_write_a((i+1) * COL_WIDTH - 1 downto i * COL_WIDTH); 82 end if; 83 84 if read_a = '1' then 85 reg_a((i+1) * COL_WIDTH - 1 downto i * COL_WIDTH) <= 86 store(to_integer(unsigned(addr_a) & to_unsigned(i, EXTRA_ADDR_BITS_A))); 87 end if; 88 end loop; 89 90 data_read_a <= reg_a; 91 end if; 92 end process; 93 94 process(clk_b) 95 begin 96 if rising_edge(clk_b) then 97 for i in 0 to COLS_B - 1 loop 98 if write_b = '1' and byteen_b(i) = '1' then 99 store(to_integer(unsigned(addr_b) & to_unsigned(i, EXTRA_ADDR_BITS_B))) := 100 data_write_b((i+1) * COL_WIDTH - 1 downto i * COL_WIDTH); 101 end if; 102 103 if read_b = '1' then 104 reg_b((i+1) * COL_WIDTH - 1 downto i * COL_WIDTH) <= 105 store(to_integer(unsigned(addr_b) & to_unsigned(i, EXTRA_ADDR_BITS_B))); 106 end if; 107 end loop; 108 109 data_read_b <= reg_b; 110 end if; 111 end process; 112end behavioral; 113