From 46ca2228b66dd959d8b1cbd03137ed294293bc18 Mon Sep 17 00:00:00 2001 From: Greek Date: Wed, 8 Dec 2021 11:22:23 +0100 Subject: [PATCH] Add and Redefine existing Dual Port RAM Implementations Simple Dual Port (Read and Write Port), and True Dual Port RAM implementations, together with their respective Altera implementations were added. The 'arch' Architectures should have the same behaviour as the Altera Implementations (single_port_ram was modified to achieve that) --- src/Tests/dual_port_ram_cfg.vhd | 4 ++ src/dual_port_ram.vhd | 51 ++++++++++++++++++ src/dual_port_ram_Altera.vhd | 48 +++++++++++++++++ src/dual_port_ram_cfg.vhd | 7 +++ src/single_port_ram.vhd | 9 ++-- src/true_dual_port_ram.vhd | 89 +++++++++++++++---------------- src/true_dual_port_ram_Altera.vhd | 58 ++++++++++++++++++++ src/true_dual_port_ram_cfg.vhd | 7 +++ 8 files changed, 222 insertions(+), 51 deletions(-) create mode 100644 src/Tests/dual_port_ram_cfg.vhd create mode 100644 src/dual_port_ram.vhd create mode 100644 src/dual_port_ram_Altera.vhd create mode 100644 src/dual_port_ram_cfg.vhd create mode 100644 src/true_dual_port_ram_Altera.vhd create mode 100644 src/true_dual_port_ram_cfg.vhd diff --git a/src/Tests/dual_port_ram_cfg.vhd b/src/Tests/dual_port_ram_cfg.vhd new file mode 100644 index 0000000..febdef0 --- /dev/null +++ b/src/Tests/dual_port_ram_cfg.vhd @@ -0,0 +1,4 @@ +configuration dual_port_ram_cfg of dual_port_ram is + for arch + end for; +end configuration; \ No newline at end of file diff --git a/src/dual_port_ram.vhd b/src/dual_port_ram.vhd new file mode 100644 index 0000000..353a3a8 --- /dev/null +++ b/src/dual_port_ram.vhd @@ -0,0 +1,51 @@ +-- altera vhdl_input_version vhdl_2008 +-- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html) + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity dual_port_ram is + generic ( + ADDR_WIDTH : natural := 8; + DATA_WIDTH : natural := 12; + MEMORY_DEPTH : natural := 256 + ); + port ( + clk : in std_logic; + raddr : in std_logic_vector(ADDR_WIDTH-1 downto 0); + waddr : in std_logic_vector(ADDR_WIDTH-1 downto 0); + wen : in std_logic; + ren : in std_logic; + wr_data : in std_logic_vector(DATA_WIDTH-1 downto 0); + rd_data : out std_logic_vector(DATA_WIDTH-1 downto 0) + ); +end entity; + +architecture arch of dual_port_ram is + + type RAM_TYPE is array (0 to MEMORY_DEPTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0); + + signal mem : RAM_TYPE := (others => (others => '0')); + +begin + + ram_prc : process(all) + begin + if rising_edge(clk) then + rd_data <= (others => '0'); + + -- Mixed Port Read-During-Write not supported + assert(not (waddr = raddr and wen = '1' and ren = '1')) severity FAILURE; + + if (wen = '1') then + mem(to_integer(unsigned(waddr))) <= wr_data; + end if; + + if (ren = '1') then + rd_data <= mem(to_integer(unsigned(raddr))); + end if; + end if; + end process; + +end architecture; diff --git a/src/dual_port_ram_Altera.vhd b/src/dual_port_ram_Altera.vhd new file mode 100644 index 0000000..e9d1b2c --- /dev/null +++ b/src/dual_port_ram_Altera.vhd @@ -0,0 +1,48 @@ +-- altera vhdl_input_version vhdl_2008 +-- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html) + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +architecture altera of dual_port_ram is + +begin + + altsyncram_component : altsyncram + generic map ( + address_aclr_b => "NONE", + address_reg_b => "CLOCK0", + clock_enable_input_a => "BYPASS", + clock_enable_input_b => "BYPASS", + clock_enable_output_b => "BYPASS", + intended_device_family => "Cyclone V", + lpm_type => "altsyncram", + numwords_a => MEMORY_DEPTH, + numwords_b => MEMORY_DEPTH, + operation_mode => "DUAL_PORT", + outdata_aclr_b => "NONE", + outdata_reg_b => "UNREGISTERED", + power_up_uninitialized => "FALSE", + rdcontrol_reg_b => "CLOCK0", + read_during_write_mode_mixed_ports => "DONT_CARE", + widthad_a => ADDR_WIDTH, + widthad_b => ADDR_WIDTH, + width_a => DATA_WIDTH, + width_b => DATA_WIDTH, + width_byteena_a => 1 + ) + port map ( + address_a => waddr, + address_b => raddr, + clock0 => clk, + data_a => wr_data, + rden_b => ren, + wren_a => wen, + q_b => rd_data + ); + +end architecture; diff --git a/src/dual_port_ram_cfg.vhd b/src/dual_port_ram_cfg.vhd new file mode 100644 index 0000000..39a1add --- /dev/null +++ b/src/dual_port_ram_cfg.vhd @@ -0,0 +1,7 @@ +-- altera vhdl_input_version vhdl_2008 +-- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html) + +configuration dual_port_ram_cfg of dual_port_ram is + for altera + end for; +end configuration; diff --git a/src/single_port_ram.vhd b/src/single_port_ram.vhd index 533e967..65b668b 100644 --- a/src/single_port_ram.vhd +++ b/src/single_port_ram.vhd @@ -34,16 +34,15 @@ begin if rising_edge(clk) then rd_data <= (others => '0'); + -- Read-During-Write not supported + assert(wen = '1' nand ren = '1') severity FAILURE; + if (wen = '1') then mem(to_integer(unsigned(addr))) <= wr_data; end if; if (ren = '1') then - if (wen = '1') then - rd_data <= wr_data; - else - rd_data <= mem(to_integer(unsigned(addr))); - end if; + rd_data <= mem(to_integer(unsigned(addr))); end if; end if; end process; diff --git a/src/true_dual_port_ram.vhd b/src/true_dual_port_ram.vhd index d645e06..9ef5a1d 100644 --- a/src/true_dual_port_ram.vhd +++ b/src/true_dual_port_ram.vhd @@ -5,9 +5,6 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -LIBRARY altera_mf; -USE altera_mf.altera_mf_components.all; - entity true_dual_port_ram is generic ( ADDR_WIDTH : natural := 8; @@ -31,49 +28,49 @@ end entity; architecture arch of true_dual_port_ram is + type RAM_TYPE is array (0 to MEMORY_DEPTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0); + + signal mem : RAM_TYPE := (others => (others => '0')); + begin - altsyncram_component : altsyncram - generic map ( - address_reg_b => "CLOCK0", - clock_enable_input_a => "BYPASS", - clock_enable_input_b => "BYPASS", - clock_enable_output_a => "BYPASS", - clock_enable_output_b => "BYPASS", - indata_reg_b => "CLOCK0", - intended_device_family => "Cyclone V", - lpm_type => "altsyncram", - numwords_a => MEMORY_DEPTH, - numwords_b => MEMORY_DEPTH, - operation_mode => "BIDIR_DUAL_PORT", - outdata_aclr_a => "NONE", - outdata_aclr_b => "NONE", - outdata_reg_a => "UNREGISTERED", - outdata_reg_b => "UNREGISTERED", - power_up_uninitialized => "FALSE", - read_during_write_mode_mixed_ports => "OLD_DATA", - read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", - read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", - widthad_a => ADDR_WIDTH, - widthad_b => ADDR_WIDTH, - width_a => DATA_WIDTH, - width_b => DATA_WIDTH, - width_byteena_a => 1, - width_byteena_b => 1, - wrcontrol_wraddress_reg_b => "CLOCK0" - ) - port map ( - address_a => addr_a, - address_b => addr_b, - clock0 => clk, - data_a => wr_data_a, - data_b => wr_data_b, - rden_a => ren_a, - rden_b => ren_b, - wren_a => wen_a, - wren_b => wen_b, - q_a => rd_data_a, - q_b => rd_data_b - ); - + ram_A_prc : process(all) + begin + if rising_edge(clk) then + -- Mixed Port Read-During-Write not supported + assert (not (addr_a = addr_b and ((ren_a = '1' and wen_b = '1') or (wen_b = '1' and ren_a = '1')))) severity FAILURE; + + -- Port A + rd_data_a <= (others => '0'); + + if (wen_a = '1') then + mem(to_integer(unsigned(addr_a))) <= wr_data_a; + end if; + + if (ren_a = '1') then + -- Same Port Read-During-Write returns New Data + if (wen_a = '1') then + rd_data_a <= wr_data_a; + else + rd_data_a <= mem(to_integer(unsigned(addr_a))); + end if; + end if; + + -- Port B + rd_data_b <= (others => '0'); + + if (wen_b = '1') then + mem(to_integer(unsigned(addr_b))) <= wr_data_b; + end if; + + if (ren_b = '1') then + -- Same Port Read-During-Write returns New Data + if (wen_b = '1') then + rd_data_b <= wr_data_b; + else + rd_data_b <= mem(to_integer(unsigned(addr_b))); + end if; + end if; + end if; + end process; end architecture; diff --git a/src/true_dual_port_ram_Altera.vhd b/src/true_dual_port_ram_Altera.vhd new file mode 100644 index 0000000..8b2411a --- /dev/null +++ b/src/true_dual_port_ram_Altera.vhd @@ -0,0 +1,58 @@ +-- altera vhdl_input_version vhdl_2008 +-- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html) + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +architecture altera of true_dual_port_ram is + +begin + + altsyncram_component : altsyncram + generic map ( + address_reg_b => "CLOCK0", + clock_enable_input_a => "BYPASS", + clock_enable_input_b => "BYPASS", + clock_enable_output_a => "BYPASS", + clock_enable_output_b => "BYPASS", + indata_reg_b => "CLOCK0", + intended_device_family => "Cyclone V", + lpm_type => "altsyncram", + numwords_a => MEMORY_DEPTH, + numwords_b => MEMORY_DEPTH, + operation_mode => "BIDIR_DUAL_PORT", + outdata_aclr_a => "NONE", + outdata_aclr_b => "NONE", + outdata_reg_a => "UNREGISTERED", + outdata_reg_b => "UNREGISTERED", + power_up_uninitialized => "FALSE", + read_during_write_mode_mixed_ports => "DONT_CARE", + read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", + read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", + widthad_a => ADDR_WIDTH, + widthad_b => ADDR_WIDTH, + width_a => DATA_WIDTH, + width_b => DATA_WIDTH, + width_byteena_a => 1, + width_byteena_b => 1, + wrcontrol_wraddress_reg_b => "CLOCK0" + ) + port map ( + address_a => addr_a, + address_b => addr_b, + clock0 => clk, + data_a => wr_data_a, + data_b => wr_data_b, + rden_a => ren_a, + rden_b => ren_b, + wren_a => wen_a, + wren_b => wen_b, + q_a => rd_data_a, + q_b => rd_data_b + ); + +end architecture; diff --git a/src/true_dual_port_ram_cfg.vhd b/src/true_dual_port_ram_cfg.vhd new file mode 100644 index 0000000..9b76aaf --- /dev/null +++ b/src/true_dual_port_ram_cfg.vhd @@ -0,0 +1,7 @@ +-- altera vhdl_input_version vhdl_2008 +-- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html) + +configuration true_dual_port_ram_cfg of true_dual_port_ram is + for altera + end for; +end configuration;