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;