Intel® Quartus® Prime Standard Edition User Guide: Design Recommendations

ID 683323
Date 9/24/2018
Public
Document Table of Contents

2.4.1.10. RAM with Byte-Enable Signals

The RAM code examples in this section show SystemVerilog and VHDL code that infers RAM with controls for writing single bytes into the memory word, or byte-enable signals.

Synthesis models byte-enable signals by creating write expressions with two indexes, and writing part of a RAM "word." With these implementations, you can also write more than one byte at once by enabling the appropriate byte enables.

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 Intel® Quartus® Prime Standard Edition integrated synthesis .

Refer to the Intel® Quartus® Prime HDL templates for parameterized examples that you can use for different address widths, and true dual port RAM examples with two read ports and two write ports.

SystemVerilog Simple Dual-Port Synchronous RAM with Byte Enable

module byte_enabled_simple_dual_port_ram  
( 
    input we, clk,
    input [5:0] waddr, raddr, // address width = 6 
    input [3:0] be,     	// 4 bytes per word
    input [31:0] wdata,  	// byte width = 8, 4 bytes per word
    output reg [31:0] q  	// byte width = 8, 4 bytes per word
);
	// use a multi-dimensional packed array
	//to model individual bytes within the word
   logic [3:0][7:0] ram[0:63];	// # words = 1 << address width

   always_ff@(posedge clk)
   begin
		if(we) begin
           if(be[0]) ram[waddr][0] <= wdata[7:0];
           if(be[1]) ram[waddr][1] <= wdata[15:8];
           if(be[2]) ram[waddr][2] <= wdata[23:16];
		if(be[3]) ram[waddr][3] <= wdata[31:24];
		end
		q <= ram[raddr];
   end
endmodule

VHDL Simple Dual-Port Synchronous RAM with Byte Enable

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

entity byte_enabled_simple_dual_port_ram is
port (
	we, clk : in  std_logic;
	waddr, raddr : in  integer range 0 to 63 ;     -- address width = 6
	be      : in  std_logic_vector (3 downto 0);   -- 4 bytes per word
	wdata   : in  std_logic_vector(31 downto 0);   -- byte width = 8
	q       : out std_logic_vector(31 downto 0) ); -- byte width = 8
end byte_enabled_simple_dual_port_ram;

architecture rtl of byte_enabled_simple_dual_port_ram is
  --  build up 2D array to hold the memory
	type word_t is array (0 to 3) of std_logic_vector(7 downto 0);
	type ram_t is array (0 to 63) of word_t;

	signal ram : ram_t;
	signal q_local : word_t;

	begin  -- Re-organize the read data from the RAM to match the output
		unpack: for i in 0 to 3 generate    
			q(8*(i+1) - 1 downto 8*i) <= q_local(i);
	end generate unpack;
        
	process(clk)
	begin
		if(rising_edge(clk)) then 
			if(we = '1') then
				if(be(0) = '1') then
					ram(waddr)(0) <= wdata(7 downto 0);
				end if;
				if be(1) = '1' then
					ram(waddr)(1) <= wdata(15 downto 8);
				end if;
				if be(2) = '1' then
					ram(waddr)(2) <= wdata(23 downto 16);
				end if;
				if be(3) = '1' then
					ram(waddr)(3) <= wdata(31 downto 24);
				end if;
			end if;
			q_local <= ram(raddr);
		end if;
	end process;  
end rtl;