From 2a75d7d8bf7b1aaf1020ec7ac93af95304903117 Mon Sep 17 00:00:00 2001 From: Konstantin Pavlov Date: Wed, 3 Jul 2024 23:53:55 +0300 Subject: [PATCH] Updated RAM templates --- .../byte_enabled_true_dual_port_ram.v | 65 ------------------ .../true_dual_port_ram_dual_clock.v | 44 ------------ .../byte_enabled_simple_dual_port_ram.sv | 37 ++++++++++ .../byte_enabled_true_dual_port_ram.sv | 65 ++++++++++++++++++ .../SystemVerilog/mixed_width_ram.sv | 47 +++++++++++++ .../mixed_width_true_dual_port_ram.sv | 57 ++++++++++++++++ .../mixed_width_true_dual_port_ram_new_rw.sv | 68 +++++++++++++++++++ .../Verilog/dual_port_rom.v | 32 +++++++++ .../Verilog/simple_dual_port_ram_dual_clock.v | 30 ++++++++ .../simple_dual_port_ram_single_clock.v | 30 ++++++++ .../Verilog/single_port_ram.v | 33 +++++++++ .../Verilog/single_port_ram_with_init.v | 44 ++++++++++++ .../Verilog/single_port_rom.v | 33 +++++++++ .../Verilog/true_dual_port_ram_dual_clock.v | 44 ++++++++++++ .../Verilog/true_dual_port_ram_single_clock.v | 44 ++++++++++++ ...nx_true_dual_port_read_first_2_clock_ram.v | 0 16 files changed, 564 insertions(+), 109 deletions(-) delete mode 100755 dual_port_ram_templates/byte_enabled_true_dual_port_ram.v delete mode 100755 dual_port_ram_templates/true_dual_port_ram_dual_clock.v create mode 100644 dual_port_single_port_ram_templates/SystemVerilog/byte_enabled_simple_dual_port_ram.sv create mode 100644 dual_port_single_port_ram_templates/SystemVerilog/byte_enabled_true_dual_port_ram.sv create mode 100644 dual_port_single_port_ram_templates/SystemVerilog/mixed_width_ram.sv create mode 100644 dual_port_single_port_ram_templates/SystemVerilog/mixed_width_true_dual_port_ram.sv create mode 100644 dual_port_single_port_ram_templates/SystemVerilog/mixed_width_true_dual_port_ram_new_rw.sv create mode 100644 dual_port_single_port_ram_templates/Verilog/dual_port_rom.v create mode 100644 dual_port_single_port_ram_templates/Verilog/simple_dual_port_ram_dual_clock.v create mode 100644 dual_port_single_port_ram_templates/Verilog/simple_dual_port_ram_single_clock.v create mode 100644 dual_port_single_port_ram_templates/Verilog/single_port_ram.v create mode 100644 dual_port_single_port_ram_templates/Verilog/single_port_ram_with_init.v create mode 100644 dual_port_single_port_ram_templates/Verilog/single_port_rom.v create mode 100644 dual_port_single_port_ram_templates/Verilog/true_dual_port_ram_dual_clock.v create mode 100644 dual_port_single_port_ram_templates/Verilog/true_dual_port_ram_single_clock.v rename {dual_port_ram_templates => dual_port_single_port_ram_templates}/xilinx_true_dual_port_read_first_2_clock_ram.v (100%) mode change 100755 => 100644 diff --git a/dual_port_ram_templates/byte_enabled_true_dual_port_ram.v b/dual_port_ram_templates/byte_enabled_true_dual_port_ram.v deleted file mode 100755 index f5a5fc5..0000000 --- a/dual_port_ram_templates/byte_enabled_true_dual_port_ram.v +++ /dev/null @@ -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 diff --git a/dual_port_ram_templates/true_dual_port_ram_dual_clock.v b/dual_port_ram_templates/true_dual_port_ram_dual_clock.v deleted file mode 100755 index 3e62d50..0000000 --- a/dual_port_ram_templates/true_dual_port_ram_dual_clock.v +++ /dev/null @@ -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 \ No newline at end of file diff --git a/dual_port_single_port_ram_templates/SystemVerilog/byte_enabled_simple_dual_port_ram.sv b/dual_port_single_port_ram_templates/SystemVerilog/byte_enabled_simple_dual_port_ram.sv new file mode 100644 index 0000000..a1d22ec --- /dev/null +++ b/dual_port_single_port_ram_templates/SystemVerilog/byte_enabled_simple_dual_port_ram.sv @@ -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 diff --git a/dual_port_single_port_ram_templates/SystemVerilog/byte_enabled_true_dual_port_ram.sv b/dual_port_single_port_ram_templates/SystemVerilog/byte_enabled_true_dual_port_ram.sv new file mode 100644 index 0000000..338b2de --- /dev/null +++ b/dual_port_single_port_ram_templates/SystemVerilog/byte_enabled_true_dual_port_ram.sv @@ -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 diff --git a/dual_port_single_port_ram_templates/SystemVerilog/mixed_width_ram.sv b/dual_port_single_port_ram_templates/SystemVerilog/mixed_width_ram.sv new file mode 100644 index 0000000..3d08f9b --- /dev/null +++ b/dual_port_single_port_ram_templates/SystemVerilog/mixed_width_ram.sv @@ -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 \ No newline at end of file diff --git a/dual_port_single_port_ram_templates/SystemVerilog/mixed_width_true_dual_port_ram.sv b/dual_port_single_port_ram_templates/SystemVerilog/mixed_width_true_dual_port_ram.sv new file mode 100644 index 0000000..8fac163 --- /dev/null +++ b/dual_port_single_port_ram_templates/SystemVerilog/mixed_width_true_dual_port_ram.sv @@ -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 \ No newline at end of file diff --git a/dual_port_single_port_ram_templates/SystemVerilog/mixed_width_true_dual_port_ram_new_rw.sv b/dual_port_single_port_ram_templates/SystemVerilog/mixed_width_true_dual_port_ram_new_rw.sv new file mode 100644 index 0000000..5ee9547 --- /dev/null +++ b/dual_port_single_port_ram_templates/SystemVerilog/mixed_width_true_dual_port_ram_new_rw.sv @@ -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 diff --git a/dual_port_single_port_ram_templates/Verilog/dual_port_rom.v b/dual_port_single_port_ram_templates/Verilog/dual_port_rom.v new file mode 100644 index 0000000..cc8287c --- /dev/null +++ b/dual_port_single_port_ram_templates/Verilog/dual_port_rom.v @@ -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 diff --git a/dual_port_single_port_ram_templates/Verilog/simple_dual_port_ram_dual_clock.v b/dual_port_single_port_ram_templates/Verilog/simple_dual_port_ram_dual_clock.v new file mode 100644 index 0000000..e1671bf --- /dev/null +++ b/dual_port_single_port_ram_templates/Verilog/simple_dual_port_ram_dual_clock.v @@ -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 diff --git a/dual_port_single_port_ram_templates/Verilog/simple_dual_port_ram_single_clock.v b/dual_port_single_port_ram_templates/Verilog/simple_dual_port_ram_single_clock.v new file mode 100644 index 0000000..530b09a --- /dev/null +++ b/dual_port_single_port_ram_templates/Verilog/simple_dual_port_ram_single_clock.v @@ -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 diff --git a/dual_port_single_port_ram_templates/Verilog/single_port_ram.v b/dual_port_single_port_ram_templates/Verilog/single_port_ram.v new file mode 100644 index 0000000..918fdb4 --- /dev/null +++ b/dual_port_single_port_ram_templates/Verilog/single_port_ram.v @@ -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 diff --git a/dual_port_single_port_ram_templates/Verilog/single_port_ram_with_init.v b/dual_port_single_port_ram_templates/Verilog/single_port_ram_with_init.v new file mode 100644 index 0000000..1b68f45 --- /dev/null +++ b/dual_port_single_port_ram_templates/Verilog/single_port_ram_with_init.v @@ -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 diff --git a/dual_port_single_port_ram_templates/Verilog/single_port_rom.v b/dual_port_single_port_ram_templates/Verilog/single_port_rom.v new file mode 100644 index 0000000..3d15de1 --- /dev/null +++ b/dual_port_single_port_ram_templates/Verilog/single_port_rom.v @@ -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 diff --git a/dual_port_single_port_ram_templates/Verilog/true_dual_port_ram_dual_clock.v b/dual_port_single_port_ram_templates/Verilog/true_dual_port_ram_dual_clock.v new file mode 100644 index 0000000..654d2d8 --- /dev/null +++ b/dual_port_single_port_ram_templates/Verilog/true_dual_port_ram_dual_clock.v @@ -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 diff --git a/dual_port_single_port_ram_templates/Verilog/true_dual_port_ram_single_clock.v b/dual_port_single_port_ram_templates/Verilog/true_dual_port_ram_single_clock.v new file mode 100644 index 0000000..aabfe96 --- /dev/null +++ b/dual_port_single_port_ram_templates/Verilog/true_dual_port_ram_single_clock.v @@ -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 diff --git a/dual_port_ram_templates/xilinx_true_dual_port_read_first_2_clock_ram.v b/dual_port_single_port_ram_templates/xilinx_true_dual_port_read_first_2_clock_ram.v old mode 100755 new mode 100644 similarity index 100% rename from dual_port_ram_templates/xilinx_true_dual_port_read_first_2_clock_ram.v rename to dual_port_single_port_ram_templates/xilinx_true_dual_port_read_first_2_clock_ram.v