aboutsummaryrefslogtreecommitdiffstats
path: root/testsuite/synth/issue1069/tdp_ram.vhdl
blob: 5dadf8589f2f0f678252614878d8dd366ef478c7 (plain)
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
library ieee;
use ieee.std_logic_1164.all,
    ieee.numeric_std.all;

entity tdp_ram is
    generic (
        ADDRWIDTH_A : positive := 12;
        WIDTH_A     : positive := 8;

        ADDRWIDTH_B : positive := 10;
        WIDTH_B     : positive := 32;

        COL_WIDTH : positive := 8
    );
    port (
        clk_a        : in  std_logic;
        read_a       : in  std_logic;
        write_a      : in  std_logic;
        byteen_a     : in  std_logic_vector(WIDTH_A/COL_WIDTH - 1 downto 0);
        addr_a       : in  std_logic_vector(ADDRWIDTH_A - 1 downto 0);
        data_read_a  : out std_logic_vector(WIDTH_A - 1 downto 0);
        data_write_a : in  std_logic_vector(WIDTH_A - 1 downto 0);

        clk_b        : in  std_logic;
        read_b       : in  std_logic;
        write_b      : in  std_logic;
        byteen_b     : in  std_logic_vector(WIDTH_B/COL_WIDTH - 1 downto 0);
        addr_b       : in  std_logic_vector(ADDRWIDTH_B - 1 downto 0);
        data_read_b  : out std_logic_vector(WIDTH_B - 1 downto 0);
        data_write_b : in  std_logic_vector(WIDTH_B - 1 downto 0)
    );
end tdp_ram;

architecture behavioral of tdp_ram is
    function log2(val : INTEGER) return natural is
        variable res : natural;
    begin
        for i in 0 to 31 loop
            if (val <= (2 ** i)) then
                res := i;
                exit;
            end if;
        end loop;

        return res;
    end function log2;

    function eq_assert(x : integer; y : integer) return integer is
    begin
        assert x = y;
        return x;
    end function eq_assert;
    
    constant COLS_A : positive := WIDTH_A / COL_WIDTH;
    constant COLS_B : positive := WIDTH_B / COL_WIDTH;

    constant TOTAL_COLS : positive := eq_assert(COLS_A * 2 ** ADDRWIDTH_A, COLS_B * 2 ** ADDRWIDTH_B);

    constant EXTRA_ADDR_BITS_A : natural := log2(COLS_A);
    constant EXTRA_ADDR_BITS_B : natural := log2(COLS_B);

    type ram_t is array(0 to TOTAL_COLS - 1) of std_logic_vector(COL_WIDTH - 1 downto 0);
    shared variable store : ram_t := (others => (others => '0'));

    signal reg_a : std_logic_vector(WIDTH_A - 1 downto 0);
    signal reg_b : std_logic_vector(WIDTH_B - 1 downto 0);
begin
    assert WIDTH_A mod COL_WIDTH = 0 and
           WIDTH_B mod COL_WIDTH = 0 and
           2 ** (ADDRWIDTH_A + EXTRA_ADDR_BITS_A) = TOTAL_COLS and
           2 ** (ADDRWIDTH_B + EXTRA_ADDR_BITS_B) = TOTAL_COLS
        report "Both WIDTH_A and WIDTH_B have to be a power-of-two multiple of COL_WIDTH"
        severity failure;

    process(clk_a)
    begin
        if rising_edge(clk_a) then
            for i in 0 to COLS_A - 1 loop
                if write_a = '1' and byteen_a(i) = '1' then
                    store(to_integer(unsigned(addr_a) & to_unsigned(i, EXTRA_ADDR_BITS_A))) :=
                        data_write_a((i+1) * COL_WIDTH - 1 downto i * COL_WIDTH);
                end if;

                if read_a = '1' then
                    reg_a((i+1) * COL_WIDTH - 1 downto i * COL_WIDTH) <=
                        store(to_integer(unsigned(addr_a) & to_unsigned(i, EXTRA_ADDR_BITS_A)));
                end if;
            end loop;

            data_read_a <= reg_a;
        end if;
    end process;

    process(clk_b)
    begin
        if rising_edge(clk_b) then
            for i in 0 to COLS_B - 1 loop
                if write_b = '1' and byteen_b(i) = '1' then
                    store(to_integer(unsigned(addr_b) & to_unsigned(i, EXTRA_ADDR_BITS_B))) :=
                        data_write_b((i+1) * COL_WIDTH - 1 downto i * COL_WIDTH);
                end if;

                if read_b = '1' then
                    reg_b((i+1) * COL_WIDTH - 1 downto i * COL_WIDTH) <=
                        store(to_integer(unsigned(addr_b) & to_unsigned(i, EXTRA_ADDR_BITS_B)));
                end if;
            end loop;

            data_read_b <= reg_b;
        end if;
    end process;
end behavioral;