mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-14 06:42:54 +08:00
Updated RAM templates
This commit is contained in:
parent
34e0e28b3c
commit
2a75d7d8bf
@ -1,65 +0,0 @@
|
|||||||
// Quartus Prime SystemVerilog Template
|
|
||||||
//
|
|
||||||
// True Dual-Port RAM with different read/write addresses and single read/write clock
|
|
||||||
// and with a control for writing single bytes into the memory word; byte enable
|
|
||||||
|
|
||||||
// Read during write produces old data on ports A and B and old data on mixed ports
|
|
||||||
// For device families that do not support this mode (e.g. Stratix V) the ram is not inferred
|
|
||||||
|
|
||||||
module byte_enabled_true_dual_port_ram
|
|
||||||
#(
|
|
||||||
parameter int
|
|
||||||
BYTE_WIDTH = 8,
|
|
||||||
ADDRESS_WIDTH = 6,
|
|
||||||
BYTES = 4,
|
|
||||||
DATA_WIDTH_R = BYTE_WIDTH * BYTES
|
|
||||||
)
|
|
||||||
(
|
|
||||||
input [ADDRESS_WIDTH-1:0] addr1,
|
|
||||||
input [ADDRESS_WIDTH-1:0] addr2,
|
|
||||||
input [BYTES-1:0] be1,
|
|
||||||
input [BYTES-1:0] be2,
|
|
||||||
input [BYTE_WIDTH-1:0] data_in1,
|
|
||||||
input [BYTE_WIDTH-1:0] data_in2,
|
|
||||||
input we1, we2, clk,
|
|
||||||
output [DATA_WIDTH_R-1:0] data_out1,
|
|
||||||
output [DATA_WIDTH_R-1:0] data_out2);
|
|
||||||
localparam RAM_DEPTH = 1 << ADDRESS_WIDTH;
|
|
||||||
|
|
||||||
// model the RAM with two dimensional packed array
|
|
||||||
logic [BYTES-1:0][BYTE_WIDTH-1:0] ram[0:RAM_DEPTH-1];
|
|
||||||
|
|
||||||
reg [DATA_WIDTH_R-1:0] data_reg1;
|
|
||||||
reg [DATA_WIDTH_R-1:0] data_reg2;
|
|
||||||
|
|
||||||
// port A
|
|
||||||
always@(posedge clk)
|
|
||||||
begin
|
|
||||||
if(we1) begin
|
|
||||||
// edit this code if using other than four bytes per word
|
|
||||||
if(be1[0]) ram[addr1][0] <= data_in1;
|
|
||||||
if(be1[1]) ram[addr1][1] <= data_in1;
|
|
||||||
if(be1[2]) ram[addr1][2] <= data_in1;
|
|
||||||
if(be1[3]) ram[addr1][3] <= data_in1;
|
|
||||||
end
|
|
||||||
data_reg1 <= ram[addr1];
|
|
||||||
end
|
|
||||||
|
|
||||||
assign data_out1 = data_reg1;
|
|
||||||
|
|
||||||
// port B
|
|
||||||
always@(posedge clk)
|
|
||||||
begin
|
|
||||||
if(we2) begin
|
|
||||||
// edit this code if using other than four bytes per word
|
|
||||||
if(be2[0]) ram[addr2][0] <= data_in2;
|
|
||||||
if(be2[1]) ram[addr2][1] <= data_in2;
|
|
||||||
if(be2[2]) ram[addr2][2] <= data_in2;
|
|
||||||
if(be2[3]) ram[addr2][3] <= data_in2;
|
|
||||||
end
|
|
||||||
data_reg2 <= ram[addr2];
|
|
||||||
end
|
|
||||||
|
|
||||||
assign data_out2 = data_reg2;
|
|
||||||
|
|
||||||
endmodule : byte_enabled_true_dual_port_ram
|
|
@ -1,44 +0,0 @@
|
|||||||
// Quartus Prime Verilog Template
|
|
||||||
// True Dual Port RAM with dual clocks
|
|
||||||
|
|
||||||
module true_dual_port_ram_dual_clock
|
|
||||||
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6)
|
|
||||||
(
|
|
||||||
input [(DATA_WIDTH-1):0] data_a, data_b,
|
|
||||||
input [(ADDR_WIDTH-1):0] addr_a, addr_b,
|
|
||||||
input we_a, we_b, clk_a, clk_b,
|
|
||||||
output reg [(DATA_WIDTH-1):0] q_a, q_b
|
|
||||||
);
|
|
||||||
|
|
||||||
// Declare the RAM variable
|
|
||||||
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
|
|
||||||
|
|
||||||
always @ (posedge clk_a)
|
|
||||||
begin
|
|
||||||
// Port A
|
|
||||||
if (we_a)
|
|
||||||
begin
|
|
||||||
ram[addr_a] <= data_a;
|
|
||||||
q_a <= data_a;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
q_a <= ram[addr_a];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always @ (posedge clk_b)
|
|
||||||
begin
|
|
||||||
// Port B
|
|
||||||
if (we_b)
|
|
||||||
begin
|
|
||||||
ram[addr_b] <= data_b;
|
|
||||||
q_b <= data_b;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
q_b <= ram[addr_b];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
|
@ -0,0 +1,37 @@
|
|||||||
|
// Quartus Prime SystemVerilog Template
|
||||||
|
//
|
||||||
|
// Simple Dual-Port RAM with different read/write addresses and single read/write clock
|
||||||
|
// and with a control for writing single bytes into the memory word; byte enable
|
||||||
|
|
||||||
|
module byte_enabled_simple_dual_port_ram
|
||||||
|
#(parameter int
|
||||||
|
ADDR_WIDTH = 6,
|
||||||
|
BYTE_WIDTH = 8,
|
||||||
|
BYTES = 4,
|
||||||
|
WIDTH = BYTES * BYTE_WIDTH
|
||||||
|
)
|
||||||
|
(
|
||||||
|
input [ADDR_WIDTH-1:0] waddr,
|
||||||
|
input [ADDR_WIDTH-1:0] raddr,
|
||||||
|
input [BYTES-1:0] be,
|
||||||
|
input [BYTE_WIDTH-1:0] wdata,
|
||||||
|
input we, clk,
|
||||||
|
output reg [WIDTH - 1:0] q
|
||||||
|
);
|
||||||
|
localparam int WORDS = 1 << ADDR_WIDTH ;
|
||||||
|
|
||||||
|
// use a multi-dimensional packed array to model individual bytes within the word
|
||||||
|
logic [BYTES-1:0][BYTE_WIDTH-1:0] ram[0:WORDS-1];
|
||||||
|
|
||||||
|
always_ff@(posedge clk)
|
||||||
|
begin
|
||||||
|
if(we) begin
|
||||||
|
// edit this code if using other than four bytes per word
|
||||||
|
if(be[0]) ram[waddr][0] <= wdata;
|
||||||
|
if(be[1]) ram[waddr][1] <= wdata;
|
||||||
|
if(be[2]) ram[waddr][2] <= wdata;
|
||||||
|
if(be[3]) ram[waddr][3] <= wdata;
|
||||||
|
end
|
||||||
|
q <= ram[raddr];
|
||||||
|
end
|
||||||
|
endmodule : byte_enabled_simple_dual_port_ram
|
@ -0,0 +1,65 @@
|
|||||||
|
// Quartus Prime SystemVerilog Template
|
||||||
|
//
|
||||||
|
// True Dual-Port RAM with different read/write addresses and single read/write clock
|
||||||
|
// and with a control for writing single bytes into the memory word; byte enable
|
||||||
|
|
||||||
|
// Read during write produces old data on ports A and B and old data on mixed ports
|
||||||
|
// For device families that do not support this mode (e.g. Stratix V) the ram is not inferred
|
||||||
|
|
||||||
|
module byte_enabled_true_dual_port_ram
|
||||||
|
#(
|
||||||
|
parameter int
|
||||||
|
BYTE_WIDTH = 8,
|
||||||
|
ADDRESS_WIDTH = 6,
|
||||||
|
BYTES = 4,
|
||||||
|
DATA_WIDTH_R = BYTE_WIDTH * BYTES
|
||||||
|
)
|
||||||
|
(
|
||||||
|
input [ADDRESS_WIDTH-1:0] addr1,
|
||||||
|
input [ADDRESS_WIDTH-1:0] addr2,
|
||||||
|
input [BYTES-1:0] be1,
|
||||||
|
input [BYTES-1:0] be2,
|
||||||
|
input [BYTE_WIDTH-1:0] data_in1,
|
||||||
|
input [BYTE_WIDTH-1:0] data_in2,
|
||||||
|
input we1, we2, clk,
|
||||||
|
output [DATA_WIDTH_R-1:0] data_out1,
|
||||||
|
output [DATA_WIDTH_R-1:0] data_out2);
|
||||||
|
localparam RAM_DEPTH = 1 << ADDRESS_WIDTH;
|
||||||
|
|
||||||
|
// model the RAM with two dimensional packed array
|
||||||
|
logic [BYTES-1:0][BYTE_WIDTH-1:0] ram[0:RAM_DEPTH-1];
|
||||||
|
|
||||||
|
reg [DATA_WIDTH_R-1:0] data_reg1;
|
||||||
|
reg [DATA_WIDTH_R-1:0] data_reg2;
|
||||||
|
|
||||||
|
// port A
|
||||||
|
always@(posedge clk)
|
||||||
|
begin
|
||||||
|
if(we1) begin
|
||||||
|
// edit this code if using other than four bytes per word
|
||||||
|
if(be1[0]) ram[addr1][0] <= data_in1;
|
||||||
|
if(be1[1]) ram[addr1][1] <= data_in1;
|
||||||
|
if(be1[2]) ram[addr1][2] <= data_in1;
|
||||||
|
if(be1[3]) ram[addr1][3] <= data_in1;
|
||||||
|
end
|
||||||
|
data_reg1 <= ram[addr1];
|
||||||
|
end
|
||||||
|
|
||||||
|
assign data_out1 = data_reg1;
|
||||||
|
|
||||||
|
// port B
|
||||||
|
always@(posedge clk)
|
||||||
|
begin
|
||||||
|
if(we2) begin
|
||||||
|
// edit this code if using other than four bytes per word
|
||||||
|
if(be2[0]) ram[addr2][0] <= data_in2;
|
||||||
|
if(be2[1]) ram[addr2][1] <= data_in2;
|
||||||
|
if(be2[2]) ram[addr2][2] <= data_in2;
|
||||||
|
if(be2[3]) ram[addr2][3] <= data_in2;
|
||||||
|
end
|
||||||
|
data_reg2 <= ram[addr2];
|
||||||
|
end
|
||||||
|
|
||||||
|
assign data_out2 = data_reg2;
|
||||||
|
|
||||||
|
endmodule : byte_enabled_true_dual_port_ram
|
@ -0,0 +1,47 @@
|
|||||||
|
// Quartus Prime SystemVerilog Template
|
||||||
|
//
|
||||||
|
// Mixed-width RAM with separate read and write addresses and data widths
|
||||||
|
// that are controlled by the parameters RW and WW. RW and WW must specify a
|
||||||
|
// read/write ratio supported by the memory blocks in your target device.
|
||||||
|
// Otherwise, Quartus Prime will not infer a RAM.
|
||||||
|
|
||||||
|
module mixed_width_ram
|
||||||
|
#(parameter int
|
||||||
|
WORDS = 256,
|
||||||
|
RW = 8,
|
||||||
|
WW = 32)
|
||||||
|
(
|
||||||
|
input we,
|
||||||
|
input clk,
|
||||||
|
input [$clog2((RW < WW) ? WORDS : (WORDS * RW)/WW) - 1 : 0] waddr,
|
||||||
|
input [WW-1:0] wdata,
|
||||||
|
input [$clog2((RW < WW) ? (WORDS * WW)/RW : WORDS) - 1 : 0] raddr,
|
||||||
|
output logic [RW-1:0] q
|
||||||
|
);
|
||||||
|
|
||||||
|
// Use a multi-dimensional packed array to model the different read/write
|
||||||
|
// width
|
||||||
|
localparam int R = (RW < WW) ? WW/RW : RW/WW;
|
||||||
|
localparam int B = (RW < WW) ? RW: WW;
|
||||||
|
|
||||||
|
logic [R-1:0][B-1:0] ram[0:WORDS-1];
|
||||||
|
|
||||||
|
generate if(RW < WW) begin
|
||||||
|
// Smaller read?
|
||||||
|
always_ff@(posedge clk)
|
||||||
|
begin
|
||||||
|
if(we) ram[waddr] <= wdata;
|
||||||
|
q <= ram[raddr / R][raddr % R];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
// Smaller write?
|
||||||
|
always_ff@(posedge clk)
|
||||||
|
begin
|
||||||
|
if(we) ram[waddr / R][waddr % R] <= wdata;
|
||||||
|
q <= ram[raddr];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
endmodule : mixed_width_ram
|
@ -0,0 +1,57 @@
|
|||||||
|
// Quartus Prime SystemVerilog Template
|
||||||
|
//
|
||||||
|
// True Dual-Port RAM with single clock and different data width on the two ports
|
||||||
|
//
|
||||||
|
// The first datawidth and the widths of the addresses are specified
|
||||||
|
// The second data width is equal to DATA_WIDTH1 * RATIO, where RATIO = (1 << (ADDRESS_WIDTH1 - ADDRESS_WIDTH2)
|
||||||
|
// RATIO must have value that is supported by the memory blocks in your target
|
||||||
|
// device. Otherwise, no RAM will be inferred.
|
||||||
|
//
|
||||||
|
// Read-during-write behavior returns old data for all combinations of read and
|
||||||
|
// write on both ports
|
||||||
|
//
|
||||||
|
// This style of RAM cannot be used on certain devices, e.g. Stratix V; in that case use the template for Dual-Port RAM with new data on read-during write on the same port
|
||||||
|
|
||||||
|
module mixed_width_true_dual_port_ram
|
||||||
|
#(parameter int
|
||||||
|
DATA_WIDTH1 = 8,
|
||||||
|
ADDRESS_WIDTH1 = 10,
|
||||||
|
ADDRESS_WIDTH2 = 8)
|
||||||
|
(
|
||||||
|
input [ADDRESS_WIDTH1-1:0] addr1,
|
||||||
|
input [ADDRESS_WIDTH2-1:0] addr2,
|
||||||
|
input [DATA_WIDTH1 -1:0] data_in1,
|
||||||
|
input [DATA_WIDTH1*(1<<(ADDRESS_WIDTH1 - ADDRESS_WIDTH2))-1:0] data_in2,
|
||||||
|
input we1, we2, clk,
|
||||||
|
output reg [DATA_WIDTH1-1 :0] data_out1,
|
||||||
|
output reg [DATA_WIDTH1*(1<<(ADDRESS_WIDTH1 - ADDRESS_WIDTH2))-1:0] data_out2);
|
||||||
|
|
||||||
|
localparam RATIO = 1 << (ADDRESS_WIDTH1 - ADDRESS_WIDTH2); // valid values are 2,4,8... family dependent
|
||||||
|
localparam DATA_WIDTH2 = DATA_WIDTH1 * RATIO;
|
||||||
|
localparam RAM_DEPTH = 1 << ADDRESS_WIDTH2;
|
||||||
|
|
||||||
|
// Use a multi-dimensional packed array to model the different read/ram width
|
||||||
|
reg [RATIO-1:0] [DATA_WIDTH1-1:0] ram[0:RAM_DEPTH-1];
|
||||||
|
|
||||||
|
reg [DATA_WIDTH1-1:0] data_reg1;
|
||||||
|
reg [DATA_WIDTH2-1:0] data_reg2;
|
||||||
|
|
||||||
|
// Port A
|
||||||
|
always@(posedge clk)
|
||||||
|
begin
|
||||||
|
if(we1)
|
||||||
|
ram[addr1 / RATIO][addr1 % RATIO] <= data_in1;
|
||||||
|
data_reg1 <= ram[addr1 / RATIO][addr1 % RATIO];
|
||||||
|
end
|
||||||
|
assign data_out1 = data_reg1;
|
||||||
|
|
||||||
|
// port B
|
||||||
|
always@(posedge clk)
|
||||||
|
begin
|
||||||
|
if(we2)
|
||||||
|
ram[addr2] <= data_in2;
|
||||||
|
data_reg2 <= ram[addr2];
|
||||||
|
end
|
||||||
|
|
||||||
|
assign data_out2 = data_reg2;
|
||||||
|
endmodule : mixed_width_true_dual_port_ram
|
@ -0,0 +1,68 @@
|
|||||||
|
// Quartus Prime SystemVerilog Template
|
||||||
|
//
|
||||||
|
// True Dual-Port RAM with single clock and different data width on the two ports and width new data on read during write on same port
|
||||||
|
//
|
||||||
|
// The first datawidth and the widths of the addresses are specified
|
||||||
|
// The second data width is equal to DATA_WIDTH1 * RATIO, where RATIO = (1 << (ADDRESS_WIDTH1 - ADDRESS_WIDTH2)
|
||||||
|
// RATIO must have value that is supported by the memory blocks in your target
|
||||||
|
// device. Otherwise, no RAM will be inferred.
|
||||||
|
//
|
||||||
|
// Read-during-write behavior returns old data for mixed ports and the new data on the same port
|
||||||
|
//
|
||||||
|
// This style of RAM can be used on certain devices, e.g. Stratix V, which do not support old data for read during write on same port
|
||||||
|
|
||||||
|
module mixed_width_true_dual_port_ram_new_rw
|
||||||
|
#(parameter int
|
||||||
|
DATA_WIDTH1 = 8,
|
||||||
|
ADDRESS_WIDTH1 = 10,
|
||||||
|
ADDRESS_WIDTH2 = 8)
|
||||||
|
(
|
||||||
|
input [ADDRESS_WIDTH1-1:0] addr1,
|
||||||
|
input [ADDRESS_WIDTH2-1:0] addr2,
|
||||||
|
input [DATA_WIDTH1 -1:0] data_in1,
|
||||||
|
input [DATA_WIDTH1*(1<<(ADDRESS_WIDTH1 - ADDRESS_WIDTH2))-1:0] data_in2,
|
||||||
|
input we1, we2, clk,
|
||||||
|
output reg [DATA_WIDTH1-1 :0] data_out1,
|
||||||
|
output reg [DATA_WIDTH1*(1<<(ADDRESS_WIDTH1 - ADDRESS_WIDTH2))-1:0] data_out2);
|
||||||
|
|
||||||
|
localparam RATIO = 1 << (ADDRESS_WIDTH1 - ADDRESS_WIDTH2); // valid values are 2,4,8... family dependent
|
||||||
|
localparam DATA_WIDTH2 = DATA_WIDTH1 * RATIO;
|
||||||
|
localparam RAM_DEPTH = 1 << ADDRESS_WIDTH2;
|
||||||
|
|
||||||
|
// Use a multi-dimensional packed array to model the different read/ram width
|
||||||
|
reg [RATIO-1:0] [DATA_WIDTH1-1:0] ram[0:RAM_DEPTH-1];
|
||||||
|
|
||||||
|
reg [DATA_WIDTH1-1:0] data_reg1;
|
||||||
|
reg [DATA_WIDTH2-1:0] data_reg2;
|
||||||
|
|
||||||
|
// Port A
|
||||||
|
always@(posedge clk)
|
||||||
|
begin
|
||||||
|
if(we1)
|
||||||
|
begin
|
||||||
|
ram[addr1 / RATIO][addr1 % RATIO] <= data_in1;
|
||||||
|
data_reg1 <= data_in1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
data_reg1 <= ram[addr1 / RATIO][addr1 % RATIO];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assign data_out1 = data_reg1;
|
||||||
|
|
||||||
|
// port B
|
||||||
|
always@(posedge clk)
|
||||||
|
begin
|
||||||
|
if(we2)
|
||||||
|
begin
|
||||||
|
ram[addr2] <= data_in2;
|
||||||
|
data_reg2 <= data_in2;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
data_reg2 <= ram[addr2];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign data_out2 = data_reg2;
|
||||||
|
endmodule : mixed_width_true_dual_port_ram_new_rw
|
32
dual_port_single_port_ram_templates/Verilog/dual_port_rom.v
Normal file
32
dual_port_single_port_ram_templates/Verilog/dual_port_rom.v
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Quartus Prime Verilog Template
|
||||||
|
// Dual Port ROM
|
||||||
|
|
||||||
|
module dual_port_rom
|
||||||
|
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=8)
|
||||||
|
(
|
||||||
|
input [(ADDR_WIDTH-1):0] addr_a, addr_b,
|
||||||
|
input clk,
|
||||||
|
output reg [(DATA_WIDTH-1):0] q_a, q_b
|
||||||
|
);
|
||||||
|
|
||||||
|
// Declare the ROM variable
|
||||||
|
reg [DATA_WIDTH-1:0] rom[2**ADDR_WIDTH-1:0];
|
||||||
|
|
||||||
|
// Initialize the ROM with $readmemb. Put the memory contents
|
||||||
|
// in the file dual_port_rom_init.txt. Without this file,
|
||||||
|
// this design will not compile.
|
||||||
|
// See Verilog LRM 1364-2001 Section 17.2.8 for details on the
|
||||||
|
// format of this file.
|
||||||
|
|
||||||
|
initial
|
||||||
|
begin
|
||||||
|
$readmemb("dual_port_rom_init.txt", rom);
|
||||||
|
end
|
||||||
|
|
||||||
|
always @ (posedge clk)
|
||||||
|
begin
|
||||||
|
q_a <= rom[addr_a];
|
||||||
|
q_b <= rom[addr_b];
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
@ -0,0 +1,30 @@
|
|||||||
|
// Quartus Prime Verilog Template
|
||||||
|
// Simple Dual Port RAM with separate read/write addresses and
|
||||||
|
// separate read/write clocks
|
||||||
|
|
||||||
|
module simple_dual_port_ram_dual_clock
|
||||||
|
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6)
|
||||||
|
(
|
||||||
|
input [(DATA_WIDTH-1):0] data,
|
||||||
|
input [(ADDR_WIDTH-1):0] read_addr, write_addr,
|
||||||
|
input we, read_clock, write_clock,
|
||||||
|
output reg [(DATA_WIDTH-1):0] q
|
||||||
|
);
|
||||||
|
|
||||||
|
// Declare the RAM variable
|
||||||
|
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
|
||||||
|
|
||||||
|
always @ (posedge write_clock)
|
||||||
|
begin
|
||||||
|
// Write
|
||||||
|
if (we)
|
||||||
|
ram[write_addr] <= data;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @ (posedge read_clock)
|
||||||
|
begin
|
||||||
|
// Read
|
||||||
|
q <= ram[read_addr];
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
@ -0,0 +1,30 @@
|
|||||||
|
// Quartus Prime Verilog Template
|
||||||
|
// Simple Dual Port RAM with separate read/write addresses and
|
||||||
|
// single read/write clock
|
||||||
|
|
||||||
|
module simple_dual_port_ram_single_clock
|
||||||
|
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6)
|
||||||
|
(
|
||||||
|
input [(DATA_WIDTH-1):0] data,
|
||||||
|
input [(ADDR_WIDTH-1):0] read_addr, write_addr,
|
||||||
|
input we, clk,
|
||||||
|
output reg [(DATA_WIDTH-1):0] q
|
||||||
|
);
|
||||||
|
|
||||||
|
// Declare the RAM variable
|
||||||
|
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
|
||||||
|
|
||||||
|
always @ (posedge clk)
|
||||||
|
begin
|
||||||
|
// Write
|
||||||
|
if (we)
|
||||||
|
ram[write_addr] <= data;
|
||||||
|
|
||||||
|
// Read (if read_addr == write_addr, return OLD data). To return
|
||||||
|
// NEW data, use = (blocking write) rather than <= (non-blocking write)
|
||||||
|
// in the write assignment. NOTE: NEW data may require extra bypass
|
||||||
|
// logic around the RAM.
|
||||||
|
q <= ram[read_addr];
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
@ -0,0 +1,33 @@
|
|||||||
|
// Quartus Prime Verilog Template
|
||||||
|
// Single port RAM with single read/write address
|
||||||
|
|
||||||
|
module single_port_ram
|
||||||
|
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6)
|
||||||
|
(
|
||||||
|
input [(DATA_WIDTH-1):0] data,
|
||||||
|
input [(ADDR_WIDTH-1):0] addr,
|
||||||
|
input we, clk,
|
||||||
|
output [(DATA_WIDTH-1):0] q
|
||||||
|
);
|
||||||
|
|
||||||
|
// Declare the RAM variable
|
||||||
|
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
|
||||||
|
|
||||||
|
// Variable to hold the registered read address
|
||||||
|
reg [ADDR_WIDTH-1:0] addr_reg;
|
||||||
|
|
||||||
|
always @ (posedge clk)
|
||||||
|
begin
|
||||||
|
// Write
|
||||||
|
if (we)
|
||||||
|
ram[addr] <= data;
|
||||||
|
|
||||||
|
addr_reg <= addr;
|
||||||
|
end
|
||||||
|
|
||||||
|
// Continuous assignment implies read returns NEW data.
|
||||||
|
// This is the natural behavior of the TriMatrix memory
|
||||||
|
// blocks in Single Port mode.
|
||||||
|
assign q = ram[addr_reg];
|
||||||
|
|
||||||
|
endmodule
|
@ -0,0 +1,44 @@
|
|||||||
|
// Quartus Prime Verilog Template
|
||||||
|
// Single port RAM with single read/write address and initial contents
|
||||||
|
// specified with an initial block
|
||||||
|
|
||||||
|
module single_port_ram_with_init
|
||||||
|
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6)
|
||||||
|
(
|
||||||
|
input [(DATA_WIDTH-1):0] data,
|
||||||
|
input [(ADDR_WIDTH-1):0] addr,
|
||||||
|
input we, clk,
|
||||||
|
output [(DATA_WIDTH-1):0] q
|
||||||
|
);
|
||||||
|
|
||||||
|
// Declare the RAM variable
|
||||||
|
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
|
||||||
|
|
||||||
|
// Variable to hold the registered read address
|
||||||
|
reg [ADDR_WIDTH-1:0] addr_reg;
|
||||||
|
|
||||||
|
// Specify the initial contents. You can also use the $readmemb
|
||||||
|
// system task to initialize the RAM variable from a text file.
|
||||||
|
// See the $readmemb template page for details.
|
||||||
|
initial
|
||||||
|
begin : INIT
|
||||||
|
integer i;
|
||||||
|
for(i = 0; i < 2**ADDR_WIDTH; i = i + 1)
|
||||||
|
ram[i] = {DATA_WIDTH{1'b1}};
|
||||||
|
end
|
||||||
|
|
||||||
|
always @ (posedge clk)
|
||||||
|
begin
|
||||||
|
// Write
|
||||||
|
if (we)
|
||||||
|
ram[addr] <= data;
|
||||||
|
|
||||||
|
addr_reg <= addr;
|
||||||
|
end
|
||||||
|
|
||||||
|
// Continuous assignment implies read returns NEW data.
|
||||||
|
// This is the natural behavior of the TriMatrix memory
|
||||||
|
// blocks in Single Port mode.
|
||||||
|
assign q = ram[addr_reg];
|
||||||
|
|
||||||
|
endmodule
|
@ -0,0 +1,33 @@
|
|||||||
|
// Quartus Prime Verilog Template
|
||||||
|
// Single Port ROM
|
||||||
|
|
||||||
|
module single_port_rom
|
||||||
|
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=8)
|
||||||
|
(
|
||||||
|
input [(ADDR_WIDTH-1):0] addr,
|
||||||
|
input clk,
|
||||||
|
output reg [(DATA_WIDTH-1):0] q
|
||||||
|
);
|
||||||
|
|
||||||
|
// Declare the ROM variable
|
||||||
|
reg [DATA_WIDTH-1:0] rom[2**ADDR_WIDTH-1:0];
|
||||||
|
|
||||||
|
// Initialize the ROM with $readmemb. Put the memory contents
|
||||||
|
// in the file single_port_rom_init.txt. Without this file,
|
||||||
|
// this design will not compile.
|
||||||
|
|
||||||
|
// See Verilog LRM 1364-2001 Section 17.2.8 for details on the
|
||||||
|
// format of this file, or see the "Using $readmemb and $readmemh"
|
||||||
|
// template later in this section.
|
||||||
|
|
||||||
|
initial
|
||||||
|
begin
|
||||||
|
$readmemb("single_port_rom_init.txt", rom);
|
||||||
|
end
|
||||||
|
|
||||||
|
always @ (posedge clk)
|
||||||
|
begin
|
||||||
|
q <= rom[addr];
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
@ -0,0 +1,44 @@
|
|||||||
|
// Quartus Prime Verilog Template
|
||||||
|
// True Dual Port RAM with dual clocks
|
||||||
|
|
||||||
|
module true_dual_port_ram_dual_clock
|
||||||
|
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6)
|
||||||
|
(
|
||||||
|
input [(DATA_WIDTH-1):0] data_a, data_b,
|
||||||
|
input [(ADDR_WIDTH-1):0] addr_a, addr_b,
|
||||||
|
input we_a, we_b, clk_a, clk_b,
|
||||||
|
output reg [(DATA_WIDTH-1):0] q_a, q_b
|
||||||
|
);
|
||||||
|
|
||||||
|
// Declare the RAM variable
|
||||||
|
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
|
||||||
|
|
||||||
|
always @ (posedge clk_a)
|
||||||
|
begin
|
||||||
|
// Port A
|
||||||
|
if (we_a)
|
||||||
|
begin
|
||||||
|
ram[addr_a] <= data_a;
|
||||||
|
q_a <= data_a;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
q_a <= ram[addr_a];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @ (posedge clk_b)
|
||||||
|
begin
|
||||||
|
// Port B
|
||||||
|
if (we_b)
|
||||||
|
begin
|
||||||
|
ram[addr_b] <= data_b;
|
||||||
|
q_b <= data_b;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
q_b <= ram[addr_b];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
@ -0,0 +1,44 @@
|
|||||||
|
// Quartus Prime Verilog Template
|
||||||
|
// True Dual Port RAM with single clock
|
||||||
|
|
||||||
|
module true_dual_port_ram_single_clock
|
||||||
|
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6)
|
||||||
|
(
|
||||||
|
input [(DATA_WIDTH-1):0] data_a, data_b,
|
||||||
|
input [(ADDR_WIDTH-1):0] addr_a, addr_b,
|
||||||
|
input we_a, we_b, clk,
|
||||||
|
output reg [(DATA_WIDTH-1):0] q_a, q_b
|
||||||
|
);
|
||||||
|
|
||||||
|
// Declare the RAM variable
|
||||||
|
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
|
||||||
|
|
||||||
|
// Port A
|
||||||
|
always @ (posedge clk)
|
||||||
|
begin
|
||||||
|
if (we_a)
|
||||||
|
begin
|
||||||
|
ram[addr_a] <= data_a;
|
||||||
|
q_a <= data_a;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
q_a <= ram[addr_a];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Port B
|
||||||
|
always @ (posedge clk)
|
||||||
|
begin
|
||||||
|
if (we_b)
|
||||||
|
begin
|
||||||
|
ram[addr_b] <= data_b;
|
||||||
|
q_b <= data_b;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
q_b <= ram[addr_b];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
Loading…
x
Reference in New Issue
Block a user