aboutsummaryrefslogtreecommitdiffstats
path: root/testsuite/synth/issue1069/tdp_ram2.vhdl
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2020-03-28 09:04:32 +0100
committerTristan Gingold <tgingold@free.fr>2020-03-28 09:04:32 +0100
commitbe59edef25d4f828579bce7221757c6a17412c58 (patch)
tree7bbe01140c8bfd92ab739f88b336606bc227033a /testsuite/synth/issue1069/tdp_ram2.vhdl
parentceda8dddc57cd3e41f187d6589804b76090a6f04 (diff)
downloadghdl-be59edef25d4f828579bce7221757c6a17412c58.tar.gz
ghdl-be59edef25d4f828579bce7221757c6a17412c58.tar.bz2
ghdl-be59edef25d4f828579bce7221757c6a17412c58.zip
testsuite/synth: add testcase for #1069
Diffstat (limited to 'testsuite/synth/issue1069/tdp_ram2.vhdl')
-rw-r--r--testsuite/synth/issue1069/tdp_ram2.vhdl109
1 files changed, 109 insertions, 0 deletions
diff --git a/testsuite/synth/issue1069/tdp_ram2.vhdl b/testsuite/synth/issue1069/tdp_ram2.vhdl
new file mode 100644
index 000000000..763c966ff
--- /dev/null
+++ b/testsuite/synth/issue1069/tdp_ram2.vhdl
@@ -0,0 +1,109 @@
+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 : positive := log2(COLS_A);
+ constant EXTRA_ADDR_BITS_B : positive := log2(COLS_B);
+
+ 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, clk_b)
+ type ram_t is array(0 to TOTAL_COLS - 1) of std_logic_vector(COL_WIDTH - 1 downto 0);
+ variable store : ram_t := (others => (others => '0'));
+
+ 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;
+
+ 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;