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