Quartus® Prime Pro Edition User Guide: Design Recommendations

ID 683082
Date 9/30/2024
Public
Document Table of Contents

1.4.1.9. Mixed-Width Dual-Port RAM

The RAM code examples in this section show SystemVerilog and VHDL code that infers RAM with data ports with different widths.

Verilog-1995 doesn't support mixed-width RAMs because the standard lacks a multi-dimensional array to model the different read width, write width, or both. Verilog-2001 doesn't support mixed-width RAMs because this type of logic requires multiple packed dimensions. Different synthesis tools may differ in their support for these memories. This section describes the inference rules for Quartus® Prime Pro Edition synthesis.

The first dimension of the multi-dimensional packed array represents the ratio of the wider port to the narrower port. The second dimension represents the narrower port width. The read and write port widths must specify a read or write ratio supported by the memory blocks in the target device. Otherwise, the synthesis tool does not infer a RAM.

Refer to the Quartus® Prime HDL templates for parameterized examples with supported combinations of read and write widths. You can also find examples of true dual port RAMs with two mixed-width read ports and two mixed-width write ports.

SystemVerilog Mixed-Width RAM with Read Width Smaller than Write Width

module mixed_width_ram    // 256x32 write and 1024x8 read
(
		input [7:0] waddr,  
		input [31:0] wdata, 
		input we, clk,
		input [9:0] raddr,
		output logic [7:0] q
);
	logic [3:0][7:0] ram[0:255];
	always_ff@(posedge clk)
		begin
			if(we) ram[waddr] <= wdata;
			q <= ram[raddr / 4][raddr % 4];
		end
endmodule : mixed_width_ram

SystemVerilog Mixed-Width RAM with Read Width Larger than Write Width

module mixed_width_ram     // 1024x8 write and 256x32 read	
(	
		input [9:0] waddr,	
		input [31:0] wdata, 	
		input we, clk, 	
		input [7:0] raddr,	
		output logic [9:0] q	
);	
	logic [3:0][7:0] ram[0:255];	
	always_ff@(posedge clk)	
		 begin	
			if(we) ram[waddr / 4][waddr % 4] <= wdata;	
			q <= ram[raddr];	
		 end	
endmodule : mixed_width_ram

VHDL Mixed-Width RAM with Read Width Smaller than Write Width

library ieee;	
use ieee.std_logic_1164.all;	
	
package ram_types is	
	type word_t is array (0 to 3) of std_logic_vector(7 downto 0);	
	type ram_t is array (0 to 255) of word_t;	
end ram_types;	
	
library ieee;	
use ieee.std_logic_1164.all;	
library work;	
use work.ram_types.all;	
	
entity mixed_width_ram is	
	port (	
		we, clk : in  std_logic;	
		waddr   : in  integer range 0 to 255;	
		wdata   : in  word_t;	
		raddr   : in  integer range 0 to 1023;	
		q       : out std_logic_vector(7 downto 0));	
end mixed_width_ram;	
	
architecture rtl of mixed_width_ram is	
	signal ram : ram_t; 	
begin  -- rtl	
	process(clk, we)	
	begin	
		if(rising_edge(clk)) then 	
			if(we = '1') then	
				ram(waddr) <= wdata;	
			end if;	
			q <= ram(raddr / 4 )(raddr mod 4);	
		end if;	
	end process;		
end rtl;

VHDL Mixed-Width RAM with Read Width Larger than Write Width

library ieee;
use ieee.std_logic_1164.all;

package ram_types is
	type word_t is array (0 to 3) of std_logic_vector(7 downto 0);
	type ram_t is array (0 to 255) of word_t;
end ram_types;

library ieee;
use ieee.std_logic_1164.all;
library work;
use work.ram_types.all;

entity mixed_width_ram is
	port (
		we, clk : in  std_logic;
		waddr   : in  integer range 0 to 1023;
		wdata   : in  std_logic_vector(7 downto 0);
		raddr   : in  integer range 0 to 255;
		q       : out word_t);
end mixed_width_ram;

architecture rtl of mixed_width_ram is
	signal ram : ram_t; 
begin  -- rtl
	process(clk, we)
	begin
		if(rising_edge(clk)) then 
			if(we = '1') then
				ram(waddr / 4)(waddr mod 4) <= wdata;
			end if;
			q <= ram(raddr);
		end if;
	end process; 
end rtl;