URL
https://opencores.org/ocsvn/mem_ctrl/mem_ctrl/trunk
Subversion Repositories mem_ctrl
Compare Revisions
- This comparison shows the changes necessary to convert path
/mem_ctrl/trunk/bench/richard
- from Rev 26 to Rev 28
- ↔ Reverse comparison
Rev 26 → Rev 28
/verilog/models/mt58l1my18d.v
0,0 → 1,218
/**************************************************************************************** |
* |
* File Name: MT58L1MY18D.V |
* Version: 1.3 |
* Date: March 8th, 1999 |
* Model: BUS Functional |
* Simulator: Model Technology |
* |
* Dependencies: None |
* |
* Author: Son P. Huynh |
* Email: sphuynh@micron.com |
* Phone: (208) 368-3825 |
* Company: Micron Technology, Inc. |
* Part #: MT58L1MY18D (1Mb x 18) |
* |
* Description: This is Micron's Syncburst SRAM (Pipelined DCD) |
* |
* Limitation: |
* |
* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY |
* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR |
* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. |
* |
* Copyright (c) 1997 Micron Semiconductor Products, Inc. |
* All rights researved |
* |
* Rev Author Date Changes |
* --- ---------------------------- ---------- --------------------------------------- |
* 1.3 Son P. Huynh 208-368-3825 03/08/1999 Improve model functionality |
* Micron Technology, Inc. |
* |
****************************************************************************************/ |
|
// DO NOT CHANGE THE TIMESCALE |
// MAKE SURE YOUR SIMULATOR USE "PS" RESOLUTION |
`timescale 1ns / 100ps |
|
module mt58l1my18d (Dq, Addr, Mode, Adv_n, Clk, Adsc_n, Adsp_n, Bwa_n, Bwb_n, Bwe_n, Gw_n, Ce_n, Ce2, Ce2_n, Oe_n, Zz); |
|
parameter addr_bits = 20; // 20 bits |
parameter data_bits = 18; // 18 bits |
parameter mem_sizes = 1048575; // 1 Mb |
parameter reg_delay = 0.1; // 100 ps |
parameter out_delay = 0.1; // 100 ps |
parameter tKQHZ = 3.5; // -6 device |
|
inout [(data_bits - 1) : 0] Dq; // Data IO |
input [(addr_bits - 1) : 0] Addr; // Address |
input Mode; // Burst Mode |
input Adv_n; // Synchronous Address Advance |
input Clk; // Clock |
input Adsc_n; // Synchronous Address Status Controller |
input Adsp_n; // Synchronous Address Status Processor |
input Bwa_n; // Synchronous Byte Write Enables |
input Bwb_n; // Synchronous Byte Write Enables |
input Bwe_n; // Byte Write Enable |
input Gw_n; // Global Write |
input Ce_n; // Synchronous Chip Enable |
input Ce2; // Synchronous Chip Enable |
input Ce2_n; // Synchronous Chip Enable |
input Oe_n; // Output Enable |
input Zz; // Snooze Mode |
|
reg [((data_bits / 2) - 1) : 0] bank0 [0 : mem_sizes]; // Memory Bank 0 |
reg [((data_bits / 2) - 1) : 0] bank1 [0 : mem_sizes]; // Memory Bank 1 |
|
reg [(data_bits - 1) : 0] din; // Input Registers |
reg [(data_bits - 1) : 0] dout; // Output Registers |
reg [(addr_bits - 1) : 0] addr_reg_in; // Address Register In |
reg [(addr_bits - 1) : 0] addr_reg_read; // Address Register for Read Operation |
reg [1 : 0] bcount; // 2-bit Burst Counter |
|
reg ce_reg; |
reg pipe_reg; |
reg bwa_reg; |
reg bwb_reg; |
reg sys_clk; |
|
wire ce = (~Ce_n & ~Ce2_n & Ce2); |
wire bwa_n = (((Bwa_n | Bwe_n) & Gw_n) | (~Ce_n & ~Adsp_n)); |
wire bwb_n = (((Bwb_n | Bwe_n) & Gw_n) | (~Ce_n & ~Adsp_n)); |
wire clr = (~Adsc_n | (~Adsp_n & ~Ce_n)); |
|
wire [(addr_bits - 1) : 0] addr_reg_write; // Address Register for Write Operation |
wire baddr1; // Burst Address 1 |
wire baddr0; // Burst Address 0 |
|
// Initialize |
initial begin |
ce_reg = 1'b0; |
sys_clk = 1'b0; |
pipe_reg = 1'b0; |
$timeformat (-9, 1, " ns", 10); // Format time unit |
end |
|
|
task mem_fill; |
input x; |
|
integer a, n, x; |
|
begin |
|
a=0; |
for(n=0;n<x;n=n+1) |
begin |
bank0[n] = a; |
bank1[n] = a+1; |
a=a+2; |
end |
|
end |
endtask |
|
// System Clock |
always begin |
@ (posedge Clk) begin |
sys_clk = ~Zz; |
end |
@ (negedge Clk) begin |
sys_clk = 1'b0; |
end |
end |
|
always @ (posedge sys_clk) begin |
// Address Register |
if (clr) addr_reg_in <= Addr; |
addr_reg_read <= {addr_reg_in [(addr_bits - 1) : 2], baddr1, baddr0}; |
|
// Binary Counter and Logic |
if ( Mode & clr) bcount <= 0; // Interleaved Burst |
else if (~Mode & clr) bcount <= Addr [1 : 0]; // Linear Burst |
else if (~Adv_n & ~clr) bcount <= (bcount + 1); // Advance Counter |
|
// Byte Write Register |
bwa_reg <= ~bwa_n; |
bwb_reg <= ~bwb_n; |
|
// Enable Register |
if (clr) ce_reg <= ce; |
|
// Pipelined Enable |
pipe_reg <= ce_reg; |
end |
|
// Burst Address Decode |
assign addr_reg_write = {addr_reg_in [(addr_bits - 1) : 2], baddr1, baddr0}; |
assign baddr1 = Mode ? (bcount [1] ^ addr_reg_in [1]) : bcount [1]; |
assign baddr0 = Mode ? (bcount [0] ^ addr_reg_in [0]) : bcount [0]; |
|
// Write Driver |
always @ (posedge Clk) begin |
#reg_delay; |
if (ce_reg & bwa_reg) begin |
din [data_bits / 2 - 1 : 0] <= Dq [data_bits / 2 - 1 : 0]; |
bank0 [addr_reg_write] <= Dq [data_bits / 2 - 1 : 0]; |
end |
if (ce_reg & bwb_reg) begin |
din [data_bits - 1 : data_bits / 2] <= Dq [data_bits - 1 : data_bits / 2]; |
bank1 [addr_reg_write] <= Dq [data_bits - 1 : data_bits / 2]; |
end |
end |
|
// Output Registers |
always @ (posedge Clk) begin |
#out_delay; |
if (~(bwa_reg | bwb_reg)) begin |
dout [data_bits / 2 - 1 : 0] <= bank0 [addr_reg_read]; |
dout [data_bits - 1 : data_bits / 2] <= bank1 [addr_reg_read]; |
end else begin |
dout [data_bits - 1 : 0] <= {data_bits{1'bz}}; |
end |
end |
|
// Output Buffers |
assign #(tKQHZ) Dq = (~Oe_n & ~Zz & pipe_reg & ~(bwa_reg | bwb_reg)) ? dout : {data_bits{1'bz}}; |
|
// Timing Check (6 ns clock cycle / 166 MHz) |
// Please download latest datasheet from our Web site: |
// http://www.micron.com/mti |
specify |
specparam tKC = 6.0, // Clock - Clock cycle time |
tKH = 2.3, // Clock HIGH time |
tKL = 2.3, // Clock LOW time |
tAS = 1.5, // Setup Times - Address |
tADSS = 1.5, // Address Status |
tAAS = 1.5, // Address Advance |
tWS = 1.5, // Byte Write Enables |
tDS = 1.5, // Data-in |
tCES = 1.5, // Chip Enable |
tAH = 0.5, // Hold Times - Address |
tADSH = 0.5, // Address Status |
tAAH = 0.5, // Address Advance |
tWH = 0.5, // Byte Write Enables |
tDH = 0.5, // Data-in |
tCEH = 0.5; // Chip Enable |
|
$width (negedge Clk, tKL); |
$width (posedge Clk, tKH); |
$period (negedge Clk, tKC); |
$period (posedge Clk, tKC); |
$setuphold (posedge Clk, Adsp_n, tADSS, tADSH); |
$setuphold (posedge Clk, Adsc_n, tADSS, tADSH); |
$setuphold (posedge Clk, Addr, tAS, tAH); |
$setuphold (posedge Clk, Bwa_n, tWS, tWH); |
$setuphold (posedge Clk, Bwb_n, tWS, tWH); |
$setuphold (posedge Clk, Bwe_n, tWS, tWH); |
$setuphold (posedge Clk, Gw_n, tWS, tWH); |
$setuphold (posedge Clk, Ce_n, tCES, tCEH); |
$setuphold (posedge Clk, Ce2, tCES, tCEH); |
$setuphold (posedge Clk, Ce2_n, tCES, tCEH); |
$setuphold (posedge Clk, Adv_n, tAAS, tAAH); |
endspecify |
|
endmodule |
|
/verilog/models/m8kx8.v
0,0 → 1,296
/////////////////////////////////////////////////////////////////////// |
//// //// |
//// CY7C185 model (Cypress 8kx8 fast asynchronous sram) //// |
//// //// |
//// //// |
//// Author: Richard Herveille //// |
//// richard@asics.ws //// |
//// www.asics.ws //// |
//// //// |
//// Downloaded from: http://www.opencores.org/projects/mem_ctrl //// |
//// //// |
/////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2002 Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
/////////////////////////////////////////////////////////////////////// |
|
// CVS Log |
// |
// $Id: m8kx8.v,v 1.1 2002-03-06 15:15:35 rherveille Exp $ |
// |
// $Date: 2002-03-06 15:15:35 $ |
// $Revision: 1.1 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
// |
// |
|
`timescale 1ns/10ps |
|
module A8Kx8(Address, dataIO, OEn, CE1n, CE2, WEn); |
|
// |
// parameters |
// |
|
// |
// inputs & outputs |
// |
input [12:0] Address; |
inout [ 7:0] dataIO; |
input OEn; |
input CE1n; |
input CE2; |
input WEn; |
|
// |
// variables |
// |
reg [ 7:0] mem_array [8191:0]; |
|
reg delayed_WE; |
reg [ 7:0] data_temp, dataIO1; |
reg is_write; |
|
wire CE = !CE1n && CE2; |
reg OE_OEn, OE_CE; |
wire OE = OE_OEn && OE_CE; |
|
reg read_cycle1, read_cycle2; |
|
time Trc; |
time Taa; |
time Toha; |
time Tace; |
time Tdoe; |
time Tlzoe; |
time Thzoe; |
time Tlzce; |
time Thzce; |
|
time Twc; |
time Tsce; |
time Taw; |
time Tpwe; |
time Tsd; |
time Thzwe; |
time Tlzwe; |
|
time CE_start, CE_end; |
time write_WE_start, read_WE_start; |
time dataIO_start; |
time Address_start; |
time OEn_start, OEn_end; |
|
initial |
begin |
read_cycle1 = 1'b0; |
read_cycle2 = 1'b0; |
|
// read cycle |
Trc = 20; |
Taa = 20; |
Toha = 5; |
Tace = 20; |
Tdoe = 9; |
Tlzoe = 3; |
Thzoe = 8; |
Tlzce = 5; // not completely accurate. Tlzce2 = 3ns |
Thzce = 8; |
|
// write cycle |
Twc = 20; |
Tsce = 15; |
Taw = 15; |
Tpwe = 15; |
Tsd = 10; |
Thzwe = 7; |
Tlzwe = 5; |
end |
|
// |
// module body |
// |
|
// assign output |
assign dataIO = (OE && !delayed_WE) ? data_temp : 8'bz; |
|
// assign times |
|
always@(posedge CE) |
begin |
CE_start <= $time; |
|
#Tlzce OE_CE <= CE; |
end |
|
always@(negedge CE) |
begin |
CE_end <= $time; |
|
#Thzce OE_CE <= CE; |
end |
|
always@(dataIO) |
begin |
dataIO_start <= $time; |
end |
|
always@(negedge WEn) |
begin |
write_WE_start <= $time; |
|
# Thzwe delayed_WE <= !WEn; |
end |
|
always@(posedge WEn) |
begin |
read_WE_start <= $time; |
|
#Tlzwe delayed_WE <= !WEn; |
end |
|
always@(Address) |
begin |
Address_start <= $time; |
end |
|
always@(negedge OEn) |
begin |
OEn_start <= $time; |
|
#Tlzoe OE_OEn <= !OEn; |
end |
|
always@(posedge OEn) |
begin |
OEn_end <= $time; |
|
#Thzoe OE_OEn <= !OEn; |
end |
// |
// write cycles |
// |
|
always@(WEn or CE) |
is_write <= !WEn && CE; |
|
// write cycle no.1 & no.3 WE controlled |
always@(posedge WEn or negedge CE) |
begin |
// check if CE asserted ( CE1n == 1'b0 && CE2 == 1'b1) |
if (is_write) |
begin |
|
// check WE valid time |
if ( ($time - write_WE_start) >= Tpwe) |
begin |
|
// check CE valid time |
if ( ($time - CE_start) >= Tsce) |
begin |
|
// check data_in setup-time |
if ( ($time - dataIO_start) >= Tsd) |
begin |
|
// check address valid time |
if ( ($time - Address_start >= Taw) ) |
mem_array[Address] <= dataIO; |
else |
$display("Address setup to WE write end violation at time %t", $time); |
end |
else |
$display("Data setup to WE write end violation at time %t", $time); |
end |
else |
$display("CE to WE write end violation at time %t", $time); |
end |
else |
$display("WE pulse width violation at time %t", $time); |
end |
end |
|
|
// |
// Read cycles |
// |
|
always@(Address or WEn or CE or OEn) |
begin |
// check if valid read cycle |
if (CE && WEn) |
begin |
if ( (($time - CE_start) >= Trc) && (CE_start >= CE_end) && |
(($time - OEn_start) >= Trc) && (OEn_start >= OEn_end) ) // ??? |
begin |
|
// check Trc |
if ( ($time - Address_start < Trc) ) |
begin |
$display("Read cycle time violation, caused by address change at time %t", $time); |
$display("CE: %t, OEn: %t, Adr: %t", $time - CE_start, $time - OEn_start, $time - Address_start); |
end |
|
// read cycle no.1 |
read_cycle1 <= 1'b1; |
read_cycle2 <= 1'b0; |
end |
else |
begin |
// read cycle no.2 |
read_cycle1 <= 1'b0; |
read_cycle2 <= 1'b1; |
end |
end |
else |
begin |
read_cycle1 = 1'b0; |
read_cycle2 = 1'b0; |
end |
end |
|
|
// perform actual read |
always |
begin |
#1; |
if (read_cycle1) |
if ( ($time - Address_start) >= Taa) |
data_temp <= mem_array[Address]; |
else if ( ($time - Address_start >= Toha) ) |
data_temp <= 8'bx; |
|
if (read_cycle2) |
if ( (($time - OEn_start) >= Tdoe) && (($time - CE_start) >= Tace) ) |
data_temp <= mem_array[Address]; |
else if ( (($time - OEn_start) >= Tlzoe) && (($time - CE_start) >= Tlzce) ) |
data_temp <= 8'bx; |
end |
|
endmodule |
|
|
|
/verilog/models/mt48lc16m16a2.v
0,0 → 1,1001
/**************************************************************************************** |
* |
* File Name: MT48LC16M16A2.V |
* Version: 1.0a |
* Date: August 4th, 2000 |
* Model: BUS Functional |
* Simulator: Model Technology |
* |
* Dependencies: None |
* |
* Author: Son P. Huynh |
* Email: sphuynh@micron.com |
* Phone: (208) 368-3825 |
* Company: Micron Technology, Inc. |
* Model: MT48LC16M16A2 (4Meg x 16 x 4 Banks) |
* |
* Description: Micron 256Mb SDRAM Verilog model |
* |
* Limitation: - Doesn't check for 4096 cycle refresh |
* |
* Note: - Set simulator resolution to "ps" timescale |
* - Set Debug = 0 to disable $display messages |
* |
* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY |
* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR |
* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. |
* |
|
* All rights researved |
* |
* Rev Author Phone Date Changes |
* ---- ---------------------------- ---------- --------------------------------------- |
* 1.0a Son Huynh 208-368-3825 08/04/2000 - Improve alternate banks read/write |
* Micron Technology Inc. access with auto precharge enable |
* |
* 0.0a Son Huynh 208-368-3825 04/29/1999 - First Release (from 64Mb rev 0.0e) |
* Micron Technology Inc. - Simple testbench included |
* |
****************************************************************************************/ |
|
`timescale 1ns / 100ps |
|
module mt48lc16m16a2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm); |
|
parameter addr_bits = 13; // 13 bits |
parameter data_bits = 16; // 16 bits |
parameter col_bits = 9; // 9 bits |
parameter mem_sizes = 4194303; // 4 Mb |
|
inout [data_bits - 1 : 0] Dq; |
input [addr_bits - 1 : 0] Addr; |
input [1 : 0] Ba; |
input Clk; |
input Cke; |
input Cs_n; |
input Ras_n; |
input Cas_n; |
input We_n; |
input [1 : 0] Dqm; |
|
reg [data_bits - 1 : 0] Bank0 [0 : mem_sizes]; |
reg [data_bits - 1 : 0] Bank1 [0 : mem_sizes]; |
reg [data_bits - 1 : 0] Bank2 [0 : mem_sizes]; |
reg [data_bits - 1 : 0] Bank3 [0 : mem_sizes]; |
|
reg [1 : 0] Bank_addr [0 : 3]; // Bank Address Pipeline |
reg [col_bits - 1 : 0] Col_addr [0 : 3]; // Column Address Pipeline |
reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline |
reg [1 : 0] Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline |
reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr; |
|
reg [addr_bits - 1 : 0] Mode_reg; |
reg [data_bits - 1 : 0] Dq_reg, Dq_dqm; |
reg [col_bits - 1 : 0] Col_temp, Burst_counter; |
|
reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate |
reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge |
|
reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command |
reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks) |
reg Auto_precharge [0 : 3]; // RW AutoPrecharge (Bank) |
reg Read_precharge [0 : 3]; // R AutoPrecharge |
reg Write_precharge [0 : 3]; // W AutoPrecharge |
reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge |
reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge |
reg [1 : 0] RW_interrupt_bank; // RW interrupt Bank |
time Count_time [0 : 3]; // RW AutoPrecharge (time after tWR = 1) |
integer Count_precharge [0 : 3]; // RW AutoPrecharge (Counter) |
|
reg Data_in_enable; |
reg Data_out_enable; |
|
reg [1 : 0] Bank, Previous_bank; |
reg [addr_bits - 1 : 0] Row; |
reg [col_bits - 1 : 0] Col, Col_brst; |
|
// Internal system clock |
reg CkeZ, Sys_clk, RAS_clk; |
|
// Commands Decode |
wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n; |
wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n; |
wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n; |
wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n; |
wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n; |
wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n; |
wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n; |
|
// Burst Length Decode |
wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0]; |
wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0]; |
wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0]; |
wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0]; |
|
// CAS Latency Decode |
wire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4]; |
wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4]; |
|
// Write Burst Mode |
wire Write_burst_mode = Mode_reg[9]; |
|
wire Debug = 1'b0; // Debug messages : 1 = On |
wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ |
|
assign Dq = Dq_reg; // DQ buffer |
|
// Commands Operation |
`define ACT 0 |
`define NOP 1 |
`define READ 2 |
`define READ_A 3 |
`define WRITE 4 |
`define WRITE_A 5 |
`define PRECH 6 |
`define A_REF 7 |
`define BST 8 |
`define LMR 9 |
|
// Timing Parameters for -7E and CAS Latency = 2 |
parameter tAC = 5.4; |
parameter tHZ = 5.4; |
parameter tOH = 2.7; |
parameter tMRD = 2.0; // 2 Clk Cycles |
parameter tRAS = 37.0; |
parameter tRC = 60.0; |
parameter tRCD = 15.0; |
parameter tRP = 15.0; |
parameter tRRD = 14.0; |
parameter tWRa = 7.0; // A2 Version - Auto precharge mode (1 Clk + 7 ns) |
parameter tWRp = 14.0; // A2 Version - Manual precharge mode (14 ns) |
|
// Timing Check variable |
integer MRD_chk; |
integer WR_counter [0 : 3]; |
time WR_time [0 : 3]; |
time WR_chkp [0 : 3]; |
time RC_chk, RRD_chk; |
time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3; |
time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3; |
time RP_chk0, RP_chk1, RP_chk2, RP_chk3; |
|
initial begin |
Dq_reg = {data_bits{1'bz}}; |
{Data_in_enable, Data_out_enable} = 0; |
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000; |
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000; |
{WR_chkp[0], WR_chkp[1], WR_chkp[2], WR_chkp[3]} = 0; |
{WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0; |
{WR_time[0], WR_time[1], WR_time[2], WR_time[3]} = 0; |
{RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0; |
{RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0; |
{MRD_chk, RC_chk, RRD_chk} = 0; |
{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0; |
{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0; |
{RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0; |
$timeformat (-9, 1, " ns", 12); |
//$readmemh("bank0.txt", Bank0); |
//$readmemh("bank1.txt", Bank1); |
//$readmemh("bank2.txt", Bank2); |
//$readmemh("bank3.txt", Bank3); |
RAS_clk = 1'b0; |
end |
|
// RAS Clk for checking tWR |
always RAS_clk = #0.5 ~RAS_clk; |
|
// System clock generator |
always begin |
@ (posedge Clk) begin |
Sys_clk = CkeZ; |
CkeZ = Cke; |
if (Cke == 1'b0 && (Data_in_enable == 1'b1 || Data_out_enable == 1'b1)) begin |
$display ("at time %t ERROR: Illegal power down or self refresh. Please make sure data bus is idle.", $time); |
end |
end |
@ (negedge Clk) begin |
Sys_clk = 1'b0; |
end |
end |
|
always @ (posedge Sys_clk) begin |
// Internal Commamd Pipelined |
Command[0] = Command[1]; |
Command[1] = Command[2]; |
Command[2] = Command[3]; |
Command[3] = `NOP; |
|
Col_addr[0] = Col_addr[1]; |
Col_addr[1] = Col_addr[2]; |
Col_addr[2] = Col_addr[3]; |
Col_addr[3] = {col_bits{1'b0}}; |
|
Bank_addr[0] = Bank_addr[1]; |
Bank_addr[1] = Bank_addr[2]; |
Bank_addr[2] = Bank_addr[3]; |
Bank_addr[3] = 2'b0; |
|
Bank_precharge[0] = Bank_precharge[1]; |
Bank_precharge[1] = Bank_precharge[2]; |
Bank_precharge[2] = Bank_precharge[3]; |
Bank_precharge[3] = 2'b0; |
|
A10_precharge[0] = A10_precharge[1]; |
A10_precharge[1] = A10_precharge[2]; |
A10_precharge[2] = A10_precharge[3]; |
A10_precharge[3] = 1'b0; |
|
// Dqm pipeline for Read |
Dqm_reg0 = Dqm_reg1; |
Dqm_reg1 = Dqm; |
|
// Read or Write with Auto Precharge Counter |
if (Auto_precharge[0] == 1'b1) begin |
Count_precharge[0] = Count_precharge[0] + 1; |
end |
if (Auto_precharge[1] == 1'b1) begin |
Count_precharge[1] = Count_precharge[1] + 1; |
end |
if (Auto_precharge[2] == 1'b1) begin |
Count_precharge[2] = Count_precharge[2] + 1; |
end |
if (Auto_precharge[3] == 1'b1) begin |
Count_precharge[3] = Count_precharge[3] + 1; |
end |
|
// Auto Precharge Timer for tWR |
if (Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) begin |
if (Count_precharge[0] == 1) begin |
Count_time[0] = $time; |
end |
if (Count_precharge[1] == 1) begin |
Count_time[1] = $time; |
end |
if (Count_precharge[2] == 1) begin |
Count_time[2] = $time; |
end |
if (Count_precharge[3] == 1) begin |
Count_time[3] = $time; |
end |
end else if (Burst_length_2 == 1'b1) begin |
if (Count_precharge[0] == 2) begin |
Count_time[0] = $time; |
end |
if (Count_precharge[1] == 2) begin |
Count_time[1] = $time; |
end |
if (Count_precharge[2] == 2) begin |
Count_time[2] = $time; |
end |
if (Count_precharge[3] == 2) begin |
Count_time[3] = $time; |
end |
end else if (Burst_length_4 == 1'b1) begin |
if (Count_precharge[0] == 4) begin |
Count_time[0] = $time; |
end |
if (Count_precharge[1] == 4) begin |
Count_time[1] = $time; |
end |
if (Count_precharge[2] == 4) begin |
Count_time[2] = $time; |
end |
if (Count_precharge[3] == 4) begin |
Count_time[3] = $time; |
end |
end else if (Burst_length_8 == 1'b1) begin |
if (Count_precharge[0] == 8) begin |
Count_time[0] = $time; |
end |
if (Count_precharge[1] == 8) begin |
Count_time[1] = $time; |
end |
if (Count_precharge[2] == 8) begin |
Count_time[2] = $time; |
end |
if (Count_precharge[3] == 8) begin |
Count_time[3] = $time; |
end |
end |
|
// tMRD Counter |
MRD_chk = MRD_chk + 1; |
|
// tWR Counter for Write |
WR_counter[0] = WR_counter[0] + 1; |
WR_counter[1] = WR_counter[1] + 1; |
WR_counter[2] = WR_counter[2] + 1; |
WR_counter[3] = WR_counter[3] + 1; |
|
// Auto Refresh |
if (Aref_enable == 1'b1) begin |
if (Debug) $display ("at time %t AREF : Auto Refresh", $time); |
// Auto Refresh to Auto Refresh |
if ($time - RC_chk < tRC) begin |
$display ("at time %t ERROR: tRC violation during Auto Refresh", $time); |
end |
|
// Precharge to Auto Refresh |
if ($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP) begin |
$display ("at time %t ERROR: tRP violation during Auto Refresh", $time); |
end |
|
// Precharge to Refresh |
if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin |
$display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time); |
end |
|
// Record Current tRC time |
RC_chk = $time; |
end |
|
// Load Mode Register |
if (Mode_reg_enable == 1'b1) begin |
// Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode |
if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin |
Mode_reg = Addr; |
if (Debug) begin |
$display ("at time %t LMR : Load Mode Register", $time); |
// CAS Latency |
if (Addr[6 : 4] == 3'b010) |
$display (" CAS Latency = 2"); |
else if (Addr[6 : 4] == 3'b011) |
$display (" CAS Latency = 3"); |
else |
$display (" CAS Latency = Reserved"); |
// Burst Length |
if (Addr[2 : 0] == 3'b000) |
$display (" Burst Length = 1"); |
else if (Addr[2 : 0] == 3'b001) |
$display (" Burst Length = 2"); |
else if (Addr[2 : 0] == 3'b010) |
$display (" Burst Length = 4"); |
else if (Addr[2 : 0] == 3'b011) |
$display (" Burst Length = 8"); |
else if (Addr[3 : 0] == 4'b0111) |
$display (" Burst Length = Full"); |
else |
$display (" Burst Length = Reserved"); |
// Burst Type |
if (Addr[3] == 1'b0) |
$display (" Burst Type = Sequential"); |
else if (Addr[3] == 1'b1) |
$display (" Burst Type = Interleaved"); |
else |
$display (" Burst Type = Reserved"); |
// Write Burst Mode |
if (Addr[9] == 1'b0) |
$display (" Write Burst Mode = Programmed Burst Length"); |
else if (Addr[9] == 1'b1) |
$display (" Write Burst Mode = Single Location Access"); |
else |
$display (" Write Burst Mode = Reserved"); |
end |
end else begin |
$display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time); |
end |
// REF to LMR |
if ($time - RC_chk < tRC) begin |
$display ("at time %t ERROR: tRC violation during Load Mode Register", $time); |
end |
// LMR to LMR |
if (MRD_chk < tMRD) begin |
$display ("at time %t ERROR: tMRD violation during Load Mode Register", $time); |
end |
MRD_chk = 0; |
end |
|
// Active Block (Latch Bank Address and Row Address) |
if (Active_enable == 1'b1) begin |
if (Ba == 2'b00 && Pc_b0 == 1'b1) begin |
{Act_b0, Pc_b0} = 2'b10; |
B0_row_addr = Addr [addr_bits - 1 : 0]; |
RCD_chk0 = $time; |
RAS_chk0 = $time; |
if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d",$time, Addr); |
// Precharge to Activate Bank 0 |
if ($time - RP_chk0 < tRP) begin |
$display("RP_chk0: %t, tRP: %t", RP_chk0, tRP); |
$display ("at time %t ERROR: tRP violation during Activate bank 0", $time); |
end |
end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin |
{Act_b1, Pc_b1} = 2'b10; |
B1_row_addr = Addr [addr_bits - 1 : 0]; |
RCD_chk1 = $time; |
RAS_chk1 = $time; |
if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d",$time, Addr); |
// Precharge to Activate Bank 1 |
if ($time - RP_chk1 < tRP) begin |
$display ("at time %t ERROR: tRP violation during Activate bank 1", $time); |
end |
end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin |
{Act_b2, Pc_b2} = 2'b10; |
B2_row_addr = Addr [addr_bits - 1 : 0]; |
RCD_chk2 = $time; |
RAS_chk2 = $time; |
if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d",$time, Addr); |
// Precharge to Activate Bank 2 |
if ($time - RP_chk2 < tRP) begin |
$display ("at time %t ERROR: tRP violation during Activate bank 2", $time); |
end |
end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin |
{Act_b3, Pc_b3} = 2'b10; |
B3_row_addr = Addr [addr_bits - 1 : 0]; |
RCD_chk3 = $time; |
RAS_chk3 = $time; |
if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d",$time, Addr); |
// Precharge to Activate Bank 3 |
if ($time - RP_chk3 < tRP) begin |
$display ("at time %t ERROR: tRP violation during Activate bank 3", $time); |
end |
end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin |
$display ("at time %t ERROR: Bank 0 is already Activated (not Precharged)", $time); |
end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin |
$display ("at time %t ERROR: Bank 1 is already Activated (not Precharged)", $time); |
end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin |
$display ("at time %t ERROR: Bank 2 is already Activated (not Precharged)", $time); |
end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin |
$display ("at time %t ERROR: Bank 3 is already Activated (not Precharged)", $time); |
end |
|
// Active Bank A to Active Bank B |
if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin |
$display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba); |
end |
|
// Load Mode Register to Active |
if (MRD_chk < tMRD ) begin |
$display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba); |
end |
|
// Auto Refresh to Activate |
if ($time - RC_chk < tRC) begin |
$display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba); |
end |
|
// Record variables for checking violation |
RRD_chk = $time; |
Previous_bank = Ba; |
end |
|
// Precharge Block |
if (Prech_enable == 1'b1) begin |
if (Addr[10] == 1'b1) begin |
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111; |
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000; |
RP_chk0 = $time; |
RP_chk1 = $time; |
RP_chk2 = $time; |
RP_chk3 = $time; |
if (Debug) $display ("at time %t PRE : Bank = ALL",$time); |
// Activate to Precharge all banks |
if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) || |
($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin |
$display ("at time %t ERROR: tRAS violation during Precharge all banks", $time); |
end |
// tWR violation check for write |
if (($time - WR_chkp[0] < tWRp) || ($time - WR_chkp[1] < tWRp) || |
($time - WR_chkp[2] < tWRp) || ($time - WR_chkp[3] < tWRp)) begin |
$display ("at time %t ERROR: tWR violation during Precharge all banks", $time); |
end |
end else if (Addr[10] == 1'b0) begin |
if (Ba == 2'b00) begin |
{Pc_b0, Act_b0} = 2'b10; |
RP_chk0 = $time; |
if (Debug) $display ("at time %t PRE : Bank = 0",$time); |
// Activate to Precharge Bank 0 |
if ($time - RAS_chk0 < tRAS) begin |
$display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time); |
end |
end else if (Ba == 2'b01) begin |
{Pc_b1, Act_b1} = 2'b10; |
RP_chk1 = $time; |
if (Debug) $display ("at time %t PRE : Bank = 1",$time); |
// Activate to Precharge Bank 1 |
if ($time - RAS_chk1 < tRAS) begin |
$display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time); |
end |
end else if (Ba == 2'b10) begin |
{Pc_b2, Act_b2} = 2'b10; |
RP_chk2 = $time; |
if (Debug) $display ("at time %t PRE : Bank = 2",$time); |
// Activate to Precharge Bank 2 |
if ($time - RAS_chk2 < tRAS) begin |
$display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time); |
end |
end else if (Ba == 2'b11) begin |
{Pc_b3, Act_b3} = 2'b10; |
RP_chk3 = $time; |
if (Debug) $display ("at time %t PRE : Bank = 3",$time); |
// Activate to Precharge Bank 3 |
if ($time - RAS_chk3 < tRAS) begin |
$display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time); |
end |
end |
// tWR violation check for write |
if ($time - WR_chkp[Ba] < tWRp) begin |
$display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba); |
end |
end |
// Terminate a Write Immediately (if same bank or all banks) |
if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin |
Data_in_enable = 1'b0; |
if (Debug) $display ("at time %t NOTE : Precharge interrupt Write Bank %d.", $time, Bank); |
if (Debug) $display ("at time %t NOTE : Make sure DQM is HIGH two cycles to meet tWR.", $time); |
if (Debug) $display ("at time %t NOTE : We suggest to use Burst Terminate command instead.", $time); |
end |
// Precharge Command Pipeline for Read |
if (Cas_latency_3 == 1'b1) begin |
Command[2] = `PRECH; |
Bank_precharge[2] = Ba; |
A10_precharge[2] = Addr[10]; |
end else if (Cas_latency_2 == 1'b1) begin |
Command[1] = `PRECH; |
Bank_precharge[1] = Ba; |
A10_precharge[1] = Addr[10]; |
end |
end |
|
// Burst terminate |
if (Burst_term == 1'b1) begin |
// Terminate a Write Immediately |
if (Data_in_enable == 1'b1) begin |
Data_in_enable = 1'b0; |
end |
// Terminate a Read Depend on CAS Latency |
if (Cas_latency_3 == 1'b1) begin |
Command[2] = `BST; |
end else if (Cas_latency_2 == 1'b1) begin |
Command[1] = `BST; |
end |
if (Debug) $display ("at time %t BST : Burst Terminate",$time); |
end |
|
// Read, Write, Column Latch |
if (Read_enable == 1'b1 || Write_enable == 1'b1) begin |
// Check to see if bank is open (ACT) |
if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) || |
(Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin |
$display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba); |
end |
|
// Activate to Read or Write |
if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD)) |
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time); |
if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD)) |
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time); |
if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD)) |
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time); |
if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD)) |
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time); |
|
// Read Command |
if (Read_enable == 1'b1) begin |
// CAS Latency pipeline |
if (Cas_latency_3 == 1'b1) begin |
if (Addr[10] == 1'b1) begin |
Command[2] = `READ_A; |
end else begin |
Command[2] = `READ; |
end |
Col_addr[2] = Addr; |
Bank_addr[2] = Ba; |
end else if (Cas_latency_2 == 1'b1) begin |
if (Addr[10] == 1'b1) begin |
Command[1] = `READ_A; |
end else begin |
Command[1] = `READ; |
end |
Col_addr[1] = Addr; |
Bank_addr[1] = Ba; |
end |
|
// Read interrupt Write (terminate Write immediately) |
if (Data_in_enable == 1'b1) begin |
Data_in_enable = 1'b0; |
// Interrupting a Write with Autoprecharge |
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin |
RW_interrupt_write[RW_interrupt_bank] = 1'b1; |
WR_time[RW_interrupt_bank] = $time; |
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank); |
else |
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Write Bank %d", $time, Ba, Bank); |
end |
end |
|
// Read interrupt Read (terminate Read after CL-1) |
if (Data_out_enable == 1'b1 && ((Cas_latency_2 == 1'b1 && ((Burst_length_2 == 1'b1 && Burst_counter < 1) || |
(Burst_length_4 == 1'b1 && Burst_counter < 3) || |
(Burst_length_8 == 1'b1 && Burst_counter < 7))) || |
(Cas_latency_3 == 1'b1 && ((Burst_length_4 == 1'b1 && Burst_counter < 2) || |
(Burst_length_8 == 1'b1 && Burst_counter < 6))))) begin |
// Interrupting a Read with Autoprecharge |
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Read_precharge[RW_interrupt_bank] == 1'b1) begin |
RW_interrupt_read[RW_interrupt_bank] = 1'b1; |
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank); |
else |
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Read Bank %d", $time, Ba, Bank); |
end |
end |
|
// Write Command |
end else if (Write_enable == 1'b1) begin |
if (Addr[10] == 1'b1) begin |
Command[0] = `WRITE_A; |
end else begin |
Command[0] = `WRITE; |
end |
Col_addr[0] = Addr; |
Bank_addr[0] = Ba; |
|
// Write interrupt Write (terminate Write immediately) |
if (Data_in_enable == 1'b1) begin |
Data_in_enable = 1'b0; |
// Interrupting a Write with Autoprecharge |
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin |
RW_interrupt_write[RW_interrupt_bank] = 1'b1; |
WR_time[RW_interrupt_bank] = $time; |
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank); |
else |
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Write Bank %d", $time, Ba, Bank); |
end |
end |
|
// Write interrupt Read (terminate Read immediately) |
if (Data_out_enable == 1'b1) begin |
Data_out_enable = 1'b0; |
// Interrupting a Read with Autoprecharge |
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Read_precharge[RW_interrupt_bank] == 1'b1) begin |
RW_interrupt_read[RW_interrupt_bank] = 1'b1; |
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank); |
else |
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Read Bank %d", $time, Ba, Bank); |
end |
end |
end |
|
// Read or Write with Auto Precharge |
if (Addr[10] == 1'b1) begin |
Auto_precharge[Ba] = 1'b1; |
Count_precharge[Ba] = 0; |
RW_interrupt_bank = Ba; |
if (Read_enable == 1'b1) begin |
Read_precharge[Ba] = 1'b1; |
end else if (Write_enable == 1'b1) begin |
Write_precharge[Ba] = 1'b1; |
end |
end |
end |
|
// Read with Auto Precharge Calculation |
// The device start internal precharge: |
// 1. CAS Latency - 1 cycles before last burst |
// and 2. Meet minimum tRAS requirement |
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge) |
if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin |
if ((($time - RAS_chk0 >= tRAS) && // Case 2 |
((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 1 |
(Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) || |
(Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) || |
(Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) || |
(RW_interrupt_read[0] == 1'b1)) begin // Case 3 |
Pc_b0 = 1'b1; |
Act_b0 = 1'b0; |
RP_chk0 = $time; |
Auto_precharge[0] = 1'b0; |
Read_precharge[0] = 1'b0; |
RW_interrupt_read[0] = 1'b0; |
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time); |
end |
end |
if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin |
if ((($time - RAS_chk1 >= tRAS) && |
((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) || |
(Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) || |
(Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) || |
(Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) || |
(RW_interrupt_read[1] == 1'b1)) begin |
Pc_b1 = 1'b1; |
Act_b1 = 1'b0; |
RP_chk1 = $time; |
Auto_precharge[1] = 1'b0; |
Read_precharge[1] = 1'b0; |
RW_interrupt_read[1] = 1'b0; |
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time); |
end |
end |
if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin |
if ((($time - RAS_chk2 >= tRAS) && |
((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) || |
(Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) || |
(Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) || |
(Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) || |
(RW_interrupt_read[2] == 1'b1)) begin |
Pc_b2 = 1'b1; |
Act_b2 = 1'b0; |
RP_chk2 = $time; |
Auto_precharge[2] = 1'b0; |
Read_precharge[2] = 1'b0; |
RW_interrupt_read[2] = 1'b0; |
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time); |
end |
end |
if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin |
if ((($time - RAS_chk3 >= tRAS) && |
((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) || |
(Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) || |
(Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) || |
(Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) || |
(RW_interrupt_read[3] == 1'b1)) begin |
Pc_b3 = 1'b1; |
Act_b3 = 1'b0; |
RP_chk3 = $time; |
Auto_precharge[3] = 1'b0; |
Read_precharge[3] = 1'b0; |
RW_interrupt_read[3] = 1'b0; |
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time); |
end |
end |
|
// Internal Precharge or Bst |
if (Command[0] == `PRECH) begin // Precharge terminate a read with same bank or all banks |
if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin |
if (Data_out_enable == 1'b1) begin |
Data_out_enable = 1'b0; |
end |
end |
end else if (Command[0] == `BST) begin // BST terminate a read to current bank |
if (Data_out_enable == 1'b1) begin |
Data_out_enable = 1'b0; |
end |
end |
|
if (Data_out_enable == 1'b0) begin |
Dq_reg <= #tOH {data_bits{1'bz}}; |
end |
|
// Detect Read or Write command |
if (Command[0] == `READ || Command[0] == `READ_A) begin |
Bank = Bank_addr[0]; |
Col = Col_addr[0]; |
Col_brst = Col_addr[0]; |
if (Bank_addr[0] == 2'b00) begin |
Row = B0_row_addr; |
end else if (Bank_addr[0] == 2'b01) begin |
Row = B1_row_addr; |
end else if (Bank_addr[0] == 2'b10) begin |
Row = B2_row_addr; |
end else if (Bank_addr[0] == 2'b11) begin |
Row = B3_row_addr; |
end |
Burst_counter = 0; |
Data_in_enable = 1'b0; |
Data_out_enable = 1'b1; |
end else if (Command[0] == `WRITE || Command[0] == `WRITE_A) begin |
Bank = Bank_addr[0]; |
Col = Col_addr[0]; |
Col_brst = Col_addr[0]; |
if (Bank_addr[0] == 2'b00) begin |
Row = B0_row_addr; |
end else if (Bank_addr[0] == 2'b01) begin |
Row = B1_row_addr; |
end else if (Bank_addr[0] == 2'b10) begin |
Row = B2_row_addr; |
end else if (Bank_addr[0] == 2'b11) begin |
Row = B3_row_addr; |
end |
Burst_counter = 0; |
Data_in_enable = 1'b1; |
Data_out_enable = 1'b0; |
end |
|
// DQ buffer (Driver/Receiver) |
if (Data_in_enable == 1'b1) begin // Writing Data to Memory |
// Array buffer |
if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}]; |
if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}]; |
if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}]; |
if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}]; |
// Dqm operation |
if (Dqm[0] == 1'b0) Dq_dqm [ 7 : 0] = Dq [ 7 : 0]; |
if (Dqm[1] == 1'b0) Dq_dqm [15 : 8] = Dq [15 : 8]; |
// Write to memory |
if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq_dqm [15 : 0]; |
if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq_dqm [15 : 0]; |
if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq_dqm [15 : 0]; |
if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq_dqm [15 : 0]; |
// Output result |
if (Dqm == 2'b11) begin |
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col); |
end else begin |
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_dqm, Dqm); |
// Record tWR time and reset counter |
WR_chkp [Bank] = $time; |
WR_counter [Bank] = 0; |
end |
// Advance burst counter subroutine |
#tHZ Burst; |
end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory |
// Array buffer |
if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}]; |
if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}]; |
if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}]; |
if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}]; |
// Dqm operation |
if (Dqm_reg0[0] == 1'b1) Dq_dqm [ 7 : 0] = 8'bz; |
if (Dqm_reg0[1] == 1'b1) Dq_dqm [15 : 8] = 8'bz; |
// Display result |
Dq_reg [15 : 0] = #tAC Dq_dqm [15 : 0]; |
if (Dqm_reg0 == 2'b11) begin |
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col); |
end else begin |
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_reg, Dqm_reg0); |
end |
// Advance burst counter subroutine |
Burst; |
end |
end |
|
// Write with Auto Precharge Calculation |
// The device start internal precharge: |
// 1. tWR Clock after last burst |
// and 2. Meet minimum tRAS requirement |
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge) |
always @ (RAS_clk) begin |
if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin |
if ((($time - RAS_chk0 >= tRAS) && // Case 2 |
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1 && $time - Count_time[0] >= tWRa) || // Case 1 |
(Burst_length_2 == 1'b1 && Count_precharge [0] >= 2 && $time - Count_time[0] >= tWRa) || |
(Burst_length_4 == 1'b1 && Count_precharge [0] >= 4 && $time - Count_time[0] >= tWRa) || |
(Burst_length_8 == 1'b1 && Count_precharge [0] >= 8 && $time - Count_time[0] >= tWRa))) || |
(RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 1 && $time - WR_time[0] >= tWRa)) begin // Case 3 (stop count when interrupt) |
Auto_precharge[0] = 1'b0; |
Write_precharge[0] = 1'b0; |
RW_interrupt_write[0] = 1'b0; |
Pc_b0 = 1'b1; |
Act_b0 = 1'b0; |
RP_chk0 = $time; |
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time); |
end |
end |
if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin |
if ((($time - RAS_chk1 >= tRAS) && |
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1 && $time - Count_time[1] >= tWRa) || |
(Burst_length_2 == 1'b1 && Count_precharge [1] >= 2 && $time - Count_time[1] >= tWRa) || |
(Burst_length_4 == 1'b1 && Count_precharge [1] >= 4 && $time - Count_time[1] >= tWRa) || |
(Burst_length_8 == 1'b1 && Count_precharge [1] >= 8 && $time - Count_time[1] >= tWRa))) || |
(RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 1 && $time - WR_time[1] >= tWRa)) begin |
Auto_precharge[1] = 1'b0; |
Write_precharge[1] = 1'b0; |
RW_interrupt_write[1] = 1'b0; |
Pc_b1 = 1'b1; |
Act_b1 = 1'b0; |
RP_chk1 = $time; |
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time); |
end |
end |
if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin |
if ((($time - RAS_chk2 >= tRAS) && |
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1 && $time - Count_time[2] >= tWRa) || |
(Burst_length_2 == 1'b1 && Count_precharge [2] >= 2 && $time - Count_time[2] >= tWRa) || |
(Burst_length_4 == 1'b1 && Count_precharge [2] >= 4 && $time - Count_time[2] >= tWRa) || |
(Burst_length_8 == 1'b1 && Count_precharge [2] >= 8 && $time - Count_time[2] >= tWRa))) || |
(RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 1 && $time - WR_time[2] >= tWRa)) begin |
Auto_precharge[2] = 1'b0; |
Write_precharge[2] = 1'b0; |
RW_interrupt_write[2] = 1'b0; |
Pc_b2 = 1'b1; |
Act_b2 = 1'b0; |
RP_chk2 = $time; |
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time); |
end |
end |
if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin |
if ((($time - RAS_chk3 >= tRAS) && |
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1 && $time - Count_time[3] >= tWRa) || |
(Burst_length_2 == 1'b1 && Count_precharge [3] >= 2 && $time - Count_time[3] >= tWRa) || |
(Burst_length_4 == 1'b1 && Count_precharge [3] >= 4 && $time - Count_time[3] >= tWRa) || |
(Burst_length_8 == 1'b1 && Count_precharge [3] >= 8 && $time - Count_time[3] >= tWRa))) || |
(RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 1 && $time - WR_time[3] >= tWRa)) begin |
Auto_precharge[3] = 1'b0; |
Write_precharge[3] = 1'b0; |
RW_interrupt_write[3] = 1'b0; |
Pc_b3 = 1'b1; |
Act_b3 = 1'b0; |
RP_chk3 = $time; |
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time); |
end |
end |
end |
|
task Burst; |
begin |
// Advance Burst Counter |
Burst_counter = Burst_counter + 1; |
|
// Burst Type |
if (Mode_reg[3] == 1'b0) begin // Sequential Burst |
Col_temp = Col + 1; |
end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst |
Col_temp[2] = Burst_counter[2] ^ Col_brst[2]; |
Col_temp[1] = Burst_counter[1] ^ Col_brst[1]; |
Col_temp[0] = Burst_counter[0] ^ Col_brst[0]; |
end |
|
// Burst Length |
if (Burst_length_2) begin // Burst Length = 2 |
Col [0] = Col_temp [0]; |
end else if (Burst_length_4) begin // Burst Length = 4 |
Col [1 : 0] = Col_temp [1 : 0]; |
end else if (Burst_length_8) begin // Burst Length = 8 |
Col [2 : 0] = Col_temp [2 : 0]; |
end else begin // Burst Length = FULL |
Col = Col_temp; |
end |
|
// Burst Read Single Write |
if (Write_burst_mode == 1'b1) begin |
Data_in_enable = 1'b0; |
end |
|
// Data Counter |
if (Burst_length_1 == 1'b1) begin |
if (Burst_counter >= 1) begin |
Data_in_enable = 1'b0; |
Data_out_enable = 1'b0; |
end |
end else if (Burst_length_2 == 1'b1) begin |
if (Burst_counter >= 2) begin |
Data_in_enable = 1'b0; |
Data_out_enable = 1'b0; |
end |
end else if (Burst_length_4 == 1'b1) begin |
if (Burst_counter >= 4) begin |
Data_in_enable = 1'b0; |
Data_out_enable = 1'b0; |
end |
end else if (Burst_length_8 == 1'b1) begin |
if (Burst_counter >= 8) begin |
Data_in_enable = 1'b0; |
Data_out_enable = 1'b0; |
end |
end |
end |
endtask |
|
// Timing Parameters for -7E and CAS Latency = 2 |
specify |
specparam |
tAH = 0.8, // Addr, Ba Hold Time |
tAS = 1.5, // Addr, Ba Setup Time |
tCH = 2.5, // Clock High-Level Width |
tCL = 2.5, // Clock Low-Level Width |
tCK = 7.5, // Clock Cycle Time |
tDH = 0.8, // Data-in Hold Time |
tDS = 1.5, // Data-in Setup Time |
tCKH = 0.8, // CKE Hold Time |
tCKS = 1.5, // CKE Setup Time |
tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time |
tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time |
$width (posedge Clk, tCH); |
$width (negedge Clk, tCL); |
$period (negedge Clk, tCK); |
$period (posedge Clk, tCK); |
$setuphold(posedge Clk, Cke, tCKS, tCKH); |
$setuphold(posedge Clk, Cs_n, tCMS, tCMH); |
$setuphold(posedge Clk, Cas_n, tCMS, tCMH); |
$setuphold(posedge Clk, Ras_n, tCMS, tCMH); |
$setuphold(posedge Clk, We_n, tCMS, tCMH); |
$setuphold(posedge Clk, Addr, tAS, tAH); |
$setuphold(posedge Clk, Ba, tAS, tAH); |
$setuphold(posedge Clk, Dqm, tCMS, tCMH); |
$setuphold(posedge Dq_chk, Dq, tDS, tDH); |
endspecify |
|
endmodule |
|
|
|
|
|
/verilog/mc_defines.v
0,0 → 1,228
///////////////////////////////////////////////////////////////////// |
//// //// |
//// WISHBONE Memory Controller Definitions //// |
//// //// |
//// //// |
//// Author: Rudolf Usselmann //// |
//// rudi@asics.ws //// |
//// //// |
//// //// |
//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2000-2002 Rudolf Usselmann //// |
//// www.asics.ws //// |
//// rudi@asics.ws //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
// CVS Log |
// |
// $Id: mc_defines.v,v 1.1 2002-03-06 15:10:34 rherveille Exp $ |
// |
// $Date: 2002-03-06 15:10:34 $ |
// $Revision: 1.1 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// Revision 1.6 2001/12/12 06:35:15 rudi |
// *** empty log message *** |
// |
// Revision 1.5 2001/12/11 02:47:19 rudi |
// |
// - Made some changes not to expect clock during reset ... |
// |
// Revision 1.4 2001/11/29 02:16:28 rudi |
// |
// |
// - More Synthesis cleanup, mostly for speed |
// - Several bug fixes |
// - Changed code to avoid auto-precharge and |
// burst-terminate combinations (apparently illegal ?) |
// Now we will do a manual precharge ... |
// |
// Revision 1.3 2001/09/10 13:44:17 rudi |
// *** empty log message *** |
// |
// Revision 1.2 2001/08/10 08:16:21 rudi |
// |
// - Changed IO names to be more clear. |
// - Uniquifyed define names to be core specific. |
// - Removed "Refresh Early" configuration |
// |
// Revision 1.1 2001/07/29 07:34:41 rudi |
// |
// |
// 1) Changed Directory Structure |
// 2) Fixed several minor bugs |
// |
// Revision 1.3 2001/06/12 15:19:49 rudi |
// |
// |
// Minor changes after running lint, and a small bug |
// fix reading csr and ba_mask registers. |
// |
// Revision 1.2 2001/06/03 11:37:17 rudi |
// |
// |
// 1) Fixed Chip Select Mask Register |
// - Power On Value is now all ones |
// - Comparison Logic is now correct |
// |
// 2) All resets are now asynchronous |
// |
// 3) Converted Power On Delay to an configurable item |
// |
// 4) Added reset to Chip Select Output Registers |
// |
// 5) Forcing all outputs to Hi-Z state during reset |
// |
// Revision 1.1.1.1 2001/05/13 09:39:38 rudi |
// Created Directory Structure |
// |
// |
// |
// |
|
`timescale 1ns / 10ps |
|
///////////////////////////////////////////////////////////////////// |
// |
// This define selects how the WISHBONE interface determines if |
// the internal register file is selected. |
// This should be a simple address decoder. "wb_addr_i" is the |
// WISHBONE address bus (32 bits wide). |
`define MC_REG_SEL (wb_addr_i[31:29] == 3'b011) |
|
// This define selects how the WISHBONE interface determines if |
// the memory is selected. |
// This should be a simple address decoder. "wb_addr_i" is the |
// WISHBONE address bus (32 bits wide). |
`define MC_MEM_SEL (wb_addr_i[31:29] == 3'h0) |
|
///////////////////////////////////////////////////////////////////// |
// |
// This are the default Power-On Reset values for Chip Select |
// |
|
// This will be defined by the run script for my test bench ... |
// Alternatively force here for synthesis ... |
`define RUDIS_TB 1 |
|
// Defines which chip select is used for Power On booting |
|
// To run my default testbench default boot CS must be 3 !!! |
`ifdef RUDIS_TB |
`define MC_DEF_SEL 3'h3 |
`else |
`define MC_DEF_SEL 3'h0 |
`endif |
|
// Defines the default (reset) TMS value for the DEF_SEL chip select |
`define MC_DEF_POR_TMS 32'hffff_ffff |
|
|
///////////////////////////////////////////////////////////////////// |
// |
// Define how many Chip Selects to Implement |
// |
`define MC_HAVE_CS1 1 |
//`define MC_HAVE_CS2 1 |
//`define MC_HAVE_CS3 1 |
//`define MC_HAVE_CS4 1 |
//`define MC_HAVE_CS5 1 |
//`define MC_HAVE_CS6 1 |
//`define MC_HAVE_CS7 1 |
|
|
// To run my default testbench those need to there !!! |
`ifdef RUDIS_TB |
`define MC_HAVE_CS2 1 |
`define MC_HAVE_CS3 1 |
`define MC_HAVE_CS4 1 |
`define MC_HAVE_CS5 1 |
`endif |
|
///////////////////////////////////////////////////////////////////// |
// |
// Init Refresh |
// |
// Number of Refresh Cycles to perform during SDRAM initialization. |
// This varies between SDRAM manufacturer. Typically this value is |
// between 2 and 8. This number must be smaller than 16. |
`define MC_INIT_RFRC_CNT 2 |
|
///////////////////////////////////////////////////////////////////// |
// |
// Power On Delay |
// |
// Most if SDRAMs require some time to initialize before they can be used |
// after power on. If the Memory Controller shall stall after power on to |
// allow SDRAMs to finish the initialization process uncomment the below |
// define statement |
`define MC_POR_DELAY 1 |
|
// This value defines how many MEM_CLK cycles the Memory Controller should |
// stall. Default is 2.5uS. At a 10nS MEM_CLK cycle time, this would 250 |
// cycles. |
`define MC_POR_DELAY_VAL 8'd250 |
|
|
// =============================================================== |
// =============================================================== |
// Various internal defines (DO NOT MODIFY !) |
// =============================================================== |
// =============================================================== |
|
// Register settings encodings |
`define MC_BW_8 2'h0 |
`define MC_BW_16 2'h1 |
`define MC_BW_32 2'h2 |
|
`define MC_MEM_TYPE_SDRAM 3'h0 |
`define MC_MEM_TYPE_SRAM 3'h1 |
`define MC_MEM_TYPE_ACS 3'h2 |
`define MC_MEM_TYPE_SCS 3'h3 |
|
`define MC_MEM_SIZE_64 2'h0 |
`define MC_MEM_SIZE_128 2'h1 |
`define MC_MEM_SIZE_256 2'h2 |
|
// Command Valid, Ras_, Cas_, We_ |
`define MC_CMD_NOP 4'b0111 |
`define MC_CMD_PC 4'b1010 |
`define MC_CMD_ACT 4'b1011 |
`define MC_CMD_WR 4'b1100 |
`define MC_CMD_RD 4'b1101 |
`define MC_CMD_BT 4'b1110 |
`define MC_CMD_ARFR 4'b1001 |
`define MC_CMD_LMR 4'b1000 |
`define MC_CMD_XRD 4'b1111 |
`define MC_CMD_XWR 4'b1110 |
|
`define MC_SINGLE_BANK 1'b0 |
`define MC_ALL_BANKS 1'b1 |
|
/verilog/tst_asram.v
0,0 → 1,265
///////////////////////////////////////////////////////////////////// |
//// //// |
//// OpenCores Memory Controller Testbench //// |
//// Asynchronous memory devices tests //// |
//// This file is being included by the main testbench //// |
//// //// |
//// Author: Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// //// |
//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2001, 2002 Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
// CVS Log |
// |
// $Id: tst_asram.v,v 1.1 2002-03-06 15:10:34 rherveille Exp $ |
// |
// $Date: 2002-03-06 15:10:34 $ |
// $Revision: 1.1 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
|
|
/////////////////////////////////////// |
// Asynchronous memory sequential test |
// |
|
// 1) Fill entire SRAM memory using sequential accesses |
// 2) Test 8/16/32 bit wide asynchronous accesses |
// 2) Verify memory contents |
// |
// THIS IS A FULL MEMORY TEST, TAKES A WHILE |
task tst_amem_seq; |
parameter MAX_CYC_DELAY = 5; |
parameter MAX_STB_DELAY = 5; |
|
parameter [31:0] SRAM_STARTA = `SRAM_LOC; |
parameter [ 7:0] SRAM_SEL = SRAM_STARTA[28:21]; |
parameter SRAM_TST_RUN = 1<<11; // entire sram memory |
|
integer n, cnt; |
reg [1:0] tmp; |
reg [31:0] my_adr; |
reg [31:0] my_dat; |
|
reg[1:0] bw; |
reg [31:0] csr_data, tms_data; |
|
integer cyc_delay, stb_delay; |
|
begin |
|
$display("\n\n --- ASYNCHRONOUS MEMORY SEQUENTIAL/FILL TEST ---\n\n"); |
|
bw = 2; |
for (bw = 0; bw < 3; bw = bw +1) |
begin |
csr_data = { |
8'h00, // reserved |
SRAM_SEL, // SEL base address (a[28:21] == 8'b0100_0000) |
4'h0, // reserved |
1'b0, // PEN no parity |
1'b0, // KRO --- |
1'b0, // BAS --- |
1'b0, // WP no write protection |
2'b00, // MS --- |
bw, // BW Bus width |
3'h2, // MEM memory type == asynchronous |
1'b1 // EN enable chip select |
}; |
|
tms_data = { |
6'h0, // reserved |
6'h0, // Twwd = 5ns => 0ns |
4'h0, // Twd = 0ns => 0ns |
4'h1, // Twpw = 15ns => 20ns |
4'h0, // Trdz = 8ns => 10ns |
8'h02 // Trdv = 20ns => 20ns |
}; |
|
// program chip select registers |
wbm.wb_write(0, 0, 32'h6000_0018, csr_data); // program cs1 config register |
wbm.wb_write(0, 0, 32'h6000_001c, tms_data); // program cs1 timing register |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0018, csr_data); |
wbm.wb_cmp(0, 0, 32'h6000_001c, tms_data); |
|
cyc_delay = 1; |
stb_delay = 1; |
for (cyc_delay = 0; cyc_delay < MAX_CYC_DELAY; cyc_delay = cyc_delay +1) |
for (stb_delay = 0; stb_delay < MAX_STB_DELAY; stb_delay = stb_delay +1) |
begin |
$display("Asynchronous memory sequential test. CYC-delay = %d, STB-delay = %d, BW = %d", cyc_delay, stb_delay, bw); |
|
// fill srams |
tmp = ~(bw +1); |
|
my_dat = 0; |
for (n=0; n < (SRAM_TST_RUN<<tmp); n=n+1) |
begin |
my_adr = SRAM_STARTA + (n << bw); |
|
cnt = (n >> tmp) + cyc_delay + stb_delay; |
|
case (bw) |
2'b00: // 8bit asynchronous memory connected |
case (n[1:0]) |
2'b00: my_dat[7:0] = ~cnt[ 7:0]; |
2'b01: my_dat[7:0] = ~cnt[15:8]; |
2'b10: my_dat[7:0] = cnt[ 7:0]; |
2'b11: my_dat[7:0] = cnt[15:8]; |
endcase |
2'b01: // 16bit asynchronous memory connected |
if (n[0]) |
my_dat[15:0] = cnt; |
else |
my_dat[15:0] = ~cnt; |
2'b10: // 32bit asynchronous memory connected |
begin |
my_dat[31:16] = cnt; |
my_dat[15: 0] = ~cnt; |
end |
2'b11: // reserved |
begin |
end |
endcase |
|
wbm.wb_write(cyc_delay, stb_delay, my_adr, my_dat); |
end |
|
// read srams |
my_dat = 0; |
for (n=0; n < SRAM_TST_RUN; n=n+1) |
begin |
my_adr = SRAM_STARTA + (n<<2); // always read 32bits |
my_dat[31:16] = (n + cyc_delay + stb_delay); |
my_dat[15: 0] = ~(n + cyc_delay + stb_delay); |
|
wbm.wb_cmp(cyc_delay, stb_delay, my_adr, my_dat); |
end |
end |
end |
|
$display("\nAsynchronous memory sequential test ended"); |
|
end |
endtask // tst_amem_seq |
|
|
/////////////////////////////////////// |
// Asynchronous memory back2back test |
// |
|
// 1) Test back-2-back read/write accesses to asynchronous memory |
task tst_amem_b2b; |
parameter MAX_CYC_DELAY = 5; |
parameter MAX_STB_DELAY = 5; |
|
parameter [31:0] SRAM_STARTA = `SRAM_LOC; |
parameter [ 7:0] SRAM_SEL = SRAM_STARTA[28:21]; |
parameter SRAM_TST_RUN = 64; // only do a few accesses |
|
integer n, cnt; |
reg [1:0] tmp; |
reg [31:0] my_adr; |
reg [31:0] my_dat; |
|
reg [31:0] csr_data, tms_data; |
|
integer cyc_delay, stb_delay; |
|
begin |
csr_data = { |
8'h00, // reserved |
SRAM_SEL, // SEL base address (a[28:21] == 8'b0100_0000) |
4'h0, // reserved |
1'b0, // PEN no parity |
1'b0, // KRO --- |
1'b0, // BAS --- |
1'b0, // WP no write protection |
2'b00, // MS --- |
2'h2, // BW 32bit Bus width |
3'h2, // MEM memory type == asynchronous |
1'b1 // EN enable chip select |
}; |
|
tms_data = { |
6'h0, // reserved |
6'h0, // Twwd = 5ns => 0ns |
4'h0, // Twd = 0ns => 0ns |
4'h1, // Twpw = 15ns => 20ns |
4'h0, // Trdz = 8ns => 10ns |
8'h02 // Trdv = 20ns => 20ns |
}; |
|
// program chip select registers |
wbm.wb_write(0, 0, 32'h6000_0018, csr_data); // program cs1 config register |
wbm.wb_write(0, 0, 32'h6000_001c, tms_data); // program cs1 timing register |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0018, csr_data); |
wbm.wb_cmp(0, 0, 32'h6000_001c, tms_data); |
|
cyc_delay = 1; |
stb_delay = 1; |
for (cyc_delay = 0; cyc_delay <= MAX_CYC_DELAY; cyc_delay = cyc_delay +1) |
for (stb_delay = 0; stb_delay <= MAX_STB_DELAY; stb_delay = stb_delay +1) |
begin |
$display("Asynchronous memory back-2-back test. CYC-delay = %d, STB-delay = %d", cyc_delay, stb_delay); |
|
// fill srams |
|
my_dat = 0; |
for (n=0; n < SRAM_TST_RUN; n=n+1) |
begin |
my_adr = SRAM_STARTA + (n << 2); |
|
cnt = n + cyc_delay + stb_delay; |
|
my_dat[31:16] = cnt; |
my_dat[15: 0] = ~cnt; |
|
wbm.wb_write(cyc_delay, stb_delay, my_adr, my_dat); |
|
// read srams |
my_adr = SRAM_STARTA + (n<<2); // always read 32bits |
wbm.wb_cmp(cyc_delay, stb_delay, my_adr, my_dat); |
end |
end |
|
$display("\nAsynchronous memory back-2-back test ended"); |
end |
endtask // tst_amem_b2b |
|
/verilog/bench.v
0,0 → 1,458
///////////////////////////////////////////////////////////////////// |
//// //// |
//// OpenCores Memory Controller Testbench //// |
//// Main testbench //// |
//// //// |
//// Author: Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// //// |
//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2001 Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
// ToDo: |
// 1) add power-on configuration |
// 2) test SSRAM |
// 3) test synchronous devices ??? |
// |
|
// CVS Log |
// |
// $Id: bench.v,v 1.1 2002-03-06 15:10:34 rherveille Exp $ |
// |
// $Date: 2002-03-06 15:10:34 $ |
// $Revision: 1.1 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
|
`include "timescale.v" |
|
`define SDRAM_ROWA_HI 12 // row address hi-bit |
`define SDRAM_COLA_HI 8 // column address hi-bit |
|
`define BA_MASK 32'h0000_00e0 // base address mask |
`define SDRAM1_LOC 32'h0400_0000 // location of sdram1 in address-space |
`define SDRAM2_LOC 32'h0800_0000 // location of sdram2 in address-space |
`define SRAM_LOC 32'h0C00_0000 // location of srams in address-space |
`define SSRAM_LOC 32'h1000_0000 // location of ssrams in address-space |
|
module bench_top(); |
|
// |
// internal wires |
// |
reg wb_clk; |
reg mc_clk; |
|
reg wb_rst; |
wire [31:0] wb_dat_i, wb_dat_o; |
wire [31:0] wb_adr_o; |
wire wb_cyc_o, wb_stb_o; |
wire [ 3:0] wb_sel_o; |
wire wb_ack_i, wb_err_i, wb_rty_i; |
|
wire wb_mc_stb; |
|
wire [23:0] mc_adr_o; |
wire [31:0] mc_dq, mc_dq_o; |
wire [ 3:0] mc_dp, mc_dp_o, pbus_o, pbus_i; |
reg [ 3:0] set_par; |
wire [31:0] par_con; |
reg sel_par, sel_pbus; |
wire par_sdram_cs; |
wire mc_doe_o; |
wire [ 3:0] mc_dqm_o; |
wire mc_we_o, mc_oe_o; |
wire mc_ras_o, mc_cas_o, mc_cke_o; |
wire [ 7:0] mc_cs_o; |
wire mc_pad_oe; |
wire mc_adsc_o, mc_adv_o, mc_zz_o; // ssram connections |
|
wire ext_br, ext_bg; |
|
// |
// hookup modules |
// |
|
// hookup watch-dog counter |
watch_dog #(1024) wdog ( |
.clk(wb_clk), |
.cyc_i(wb_cyc_o), |
.ack_i(wb_ack_i), |
.adr_i(wb_adr_o) |
); |
|
// hookup external bus-master model |
bm_model ext_bm( |
.br(ext_br), |
.bg(ext_bg), |
.chk(mc_pad_oe) |
); |
|
// hookup ERR checker |
err_check err_chk(wb_err_i, sel_par); |
|
// hookup CSn checker |
cs_check cs_chec(mc_cs_o); |
|
// hookup memory controller |
mc_top dut ( |
// wishbone interface |
.clk_i(wb_clk), |
.rst_i(wb_rst), |
.wb_data_i(wb_dat_o), |
.wb_data_o(wb_dat_i), |
.wb_addr_i(wb_adr_o), |
.wb_sel_i(wb_sel_o), |
.wb_we_i(wb_we_o), |
.wb_cyc_i(wb_cyc_o), |
.wb_stb_i(wb_stb_o), |
.wb_ack_o(wb_ack_i), |
.wb_err_o(wb_err_i), |
|
// memory controller |
.susp_req_i(1'b0), |
.resume_req_i(1'b0), |
.suspended_o(), |
.poc_o(), |
.mc_clk_i(mc_clk), |
.mc_br_pad_i(ext_br), |
.mc_bg_pad_o(ext_bg), |
.mc_ack_pad_i(1'b0), |
.mc_addr_pad_o(mc_adr_o), |
.mc_data_pad_i(mc_dq), |
.mc_data_pad_o(mc_dq_o), |
.mc_dp_pad_i(pbus_i), // attach parity bus |
.mc_dp_pad_o(mc_dp_o), |
.mc_doe_pad_doe_o(mc_doe_o), |
.mc_dqm_pad_o(mc_dqm_o), |
.mc_oe_pad_o_(mc_oe_o), |
.mc_we_pad_o_(mc_we_o), |
.mc_cas_pad_o_(mc_cas_o), |
.mc_ras_pad_o_(mc_ras_o), |
.mc_cke_pad_o_(mc_cke_o), |
.mc_cs_pad_o_(mc_cs_o), |
.mc_sts_pad_i(1'b0), |
.mc_rp_pad_o_(), |
.mc_vpen_pad_o(), |
.mc_adsc_pad_o_(mc_adsc_o), |
.mc_adv_pad_o_(mc_adv_o), |
.mc_zz_pad_o(mc_zz_o), |
.mc_coe_pad_coe_o(mc_pad_oe) |
); |
|
// assign memory controller stb_signal |
assign wb_mc_stb = wb_adr_o[31]; |
|
// generate output buffers for memory controller |
assign mc_dq = mc_doe_o ? mc_dq_o : 32'bz; |
assign mc_dp = mc_doe_o ? mc_dp_o : 4'bz; |
|
// hookup ssrams (CHIP SELECT 4) |
mt58l1my18d ssram0 ( |
.Dq( {par_con[24], par_con[16], mc_dq[31:16]} ), |
.Addr(mc_adr_o[19:0]), |
.Mode(1'b0), // This input (sometimes called LBO) selects burst order |
// 1'b0 = linear burst, 1'b1 = interleaved burst |
.Adv_n(mc_adv_o), |
.Clk(mc_clk), |
.Adsc_n(mc_adsc_o), |
.Adsp_n(1'b1), |
.Bwa_n(mc_dqm_o[3]), |
.Bwb_n(mc_dqm_o[2]), // or the otherway around |
.Bwe_n(mc_we_o), |
.Gw_n(1'b1), // ?? |
.Ce_n(mc_cs_o[4]), |
.Ce2(1'b1), |
.Ce2_n(1'b0), |
.Oe_n(mc_oe_o), |
.Zz(mc_zz_o) |
); |
|
mt58l1my18d ssram1 ( |
.Dq( {par_con[8], par_con[0], mc_dq[15:0]} ), |
.Addr(mc_adr_o[19:0]), |
.Mode(1'b0), // This input (sometimes called LBO) selects burst order |
// 1'b0 = linear burst, 1'b1 = interleaved burst |
.Adv_n(mc_adv_o), |
.Clk(mc_clk), |
.Adsc_n(mc_adsc_o), |
.Adsp_n(1'b1), |
.Bwa_n(mc_dqm_o[1]), |
.Bwb_n(mc_dqm_o[0]), // or the otherway around |
.Bwe_n(mc_we_o), |
.Gw_n(1'b1), |
.Ce_n(mc_cs_o[4]), |
.Ce2(1'b1), |
.Ce2_n(1'b0), |
.Oe_n(mc_oe_o), |
.Zz(mc_zz_o) |
); |
|
|
// hookup sdrams (CHIP SELECT 3) |
mt48lc16m16a2 sdram0_3( |
.Dq(mc_dq[31:16]), |
.Addr(mc_adr_o[12:0]), |
.Ba(mc_adr_o[14:13]), |
.Clk(mc_clk), |
.Cke(mc_cke_o), |
.Cs_n(mc_cs_o[3]), |
.Ras_n(mc_ras_o), |
.Cas_n(mc_cas_o), |
.We_n(mc_we_o), |
.Dqm(mc_dqm_o[3:2]) |
); |
|
mt48lc16m16a2 sdram1_3( |
.Dq(mc_dq[15:0]), |
.Addr(mc_adr_o[12:0]), |
.Ba(mc_adr_o[14:13]), |
.Clk(mc_clk), |
.Cke(mc_cke_o), |
.Cs_n(mc_cs_o[3]), |
.Ras_n(mc_ras_o), |
.Cas_n(mc_cas_o), |
.We_n(mc_we_o), |
.Dqm(mc_dqm_o[1:0]) |
); |
|
// hookup sdrams (CHIP SELECT 2 or PARITY) |
assign pbus_o = sel_pbus ? (sel_par ? mc_dp : set_par) : mc_dq; |
assign par_con = {7'bz, pbus_o[3], 7'bz, pbus_o[2], 7'bz, pbus_o[1], 7'bz, pbus_o[0]}; |
assign pbus_i = {par_con[24], par_con[16], par_con[8], par_con[0]}; |
|
assign par_sdram_cs = sel_pbus ? mc_cs_o[3] : mc_cs_o[2]; |
|
mt48lc16m16a2 sdram0_2( |
.Dq(par_con[31:16]), |
.Addr(mc_adr_o[12:0]), |
.Ba(mc_adr_o[14:13]), |
.Clk(mc_clk), |
.Cke(mc_cke_o), |
.Cs_n(par_sdram_cs), |
.Ras_n(mc_ras_o), |
.Cas_n(mc_cas_o), |
.We_n(mc_we_o), |
.Dqm(mc_dqm_o[3:2]) |
); |
|
mt48lc16m16a2 sdram1_2( |
.Dq(par_con[15:0]), |
.Addr(mc_adr_o[12:0]), |
.Ba(mc_adr_o[14:13]), |
.Clk(mc_clk), |
.Cke(mc_cke_o), |
.Cs_n(par_sdram_cs), |
.Ras_n(mc_ras_o), |
.Cas_n(mc_cas_o), |
.We_n(mc_we_o), |
.Dqm(mc_dqm_o[1:0]) |
); |
|
// hookup asynchronous srams (CHIP SELECT 1) |
A8Kx8 asram0 ( |
.Address(mc_adr_o[12:0]), |
.dataIO(mc_dq[31:24]), |
.OEn(mc_oe_o), |
.CE1n(mc_cs_o[1]), |
.CE2(1'b1), |
.WEn(mc_we_o) |
); |
|
A8Kx8 asram1 ( |
.Address(mc_adr_o[12:0]), |
.dataIO(mc_dq[23:16]), |
.OEn(mc_oe_o), |
.CE1n(mc_cs_o[1]), |
.CE2(1'b1), |
.WEn(mc_we_o) |
); |
|
A8Kx8 asram2 ( |
.Address(mc_adr_o[12:0]), |
.dataIO(mc_dq[15: 8]), |
.OEn(mc_oe_o), |
.CE1n(mc_cs_o[1]), |
.CE2(1'b1), |
.WEn(mc_we_o) |
); |
|
A8Kx8 asram3 ( |
.Address(mc_adr_o[12:0]), |
.dataIO(mc_dq[ 7: 0]), |
.OEn(mc_oe_o), |
.CE1n(mc_cs_o[1]), |
.CE2(1'b1), |
.WEn(mc_we_o) |
); |
|
// hookup wishbone master |
wb_master_model wbm( |
.clk(wb_clk), |
.rst(wb_rst), |
.adr(wb_adr_o), |
.din(wb_dat_i), |
.dout(wb_dat_o), |
.cyc(wb_cyc_o), |
.stb(wb_stb_o), |
.we(wb_we_o), |
.sel(wb_sel_o), |
.ack(wb_ack_i), |
.err(wb_err_i), |
.rty(wb_rty_i) |
); |
|
|
// |
// testbench body |
// |
|
assign wb_rty_i = 1'b0; // no retries from memory controller |
|
// generate clock |
always #2.5 wb_clk <= ~wb_clk; |
|
always@(posedge wb_clk) |
// mc_clk <= #1 ~mc_clk; |
mc_clk <= #0 ~mc_clk; |
|
// initial statements |
initial |
begin |
wb_clk = 0; // start with low-level clock |
wb_rst = 1; // assert reset |
mc_clk = 0; |
sel_par = 1; // do not modify parity bits |
sel_pbus = 1; // use second SDRAMS set as parity sdrams |
|
repeat(20) @(posedge wb_clk); |
wb_rst = 0; // negate reset |
|
@(posedge wb_clk); |
run_tests; |
|
// show total errors detected |
wbm.show_tot_err_cnt; |
|
$stop; |
end |
|
|
////////////////////// |
// |
// Internal tasks |
// |
|
task run_tests; |
begin |
prg_mc; // program memory controller BA-mask and CSR registers |
|
// force sdram0_3.Debug = 1'b1; // turn on SDRAM debug option |
force sdram0_3.Debug = 1'b0; // turn off SDRAM debug option |
|
/////////////// |
// SDRAM tests |
// tst_sdram_memfill; // test sdrams: Fill entire memory and verify |
// tst_sdram_parity; // test sdrams: Parity generation |
// tst_sdram_seq; // test sdrams: Fill-Verify, sequential access |
// tst_sdram_rnd; // test sdrams: Fill-Verify, random access |
// tst_sdram_rmw_seq; // test sdrams: Read-Modify-Write test, sequential access |
// tst_sdram_rmw_rnd; // test sdrams: Read-Modify-Write test, random access |
// tst_sdram_blk_cpy1; // test sdrams: Perform block copy, different src and dest. address |
// tst_sdram_blk_cpy2; // test sdrams: Perform block copy, src and dest same address |
// tst_sdram_bytes; // test sdrams: Peform byte accesses |
|
////////////////////////////// |
// ASYNCHRONOUS MEMORIES TEST |
// tst_amem_seq; // test asynchronous memory |
tst_amem_b2b; // test asynchronous memory back-2-back |
|
//////////////// |
// SSRAMS TESTS |
tst_ssram_seq; |
|
////////////////////// |
// MULTI MEMORY TESTS |
// tst_blk_cpy1; // test block-copy: access sdrams + asrams |
|
// The next test (tst_blk_cyp2) is, saddly to say, useless. |
// It tests n-by-n situations for multiple SDRAMS, testing all possible settings for each SDRAM. |
// It is supposed to test the independence for each SDRAM chip-select. |
// However it is to time-consuming; it runs for about a month on an Athlon-XP 1800 system |
// tst_blk_cpy2; // test block-copy: access multiple sdrams |
|
|
///////////////////////////// |
// EXTERNAL BUS MASTER TESTS |
// turn on external bus-master and rerun some tests |
// force ext_bm.on_off = 1'b1; |
// tst_sdram_seq; // test sdrams: Fill-Verify, sequential access |
// tst_amem_seq; // test asynchronous memory |
// tst_amem_b2b; // test asynchronous memory back-2-back |
// tst_blk_cpy1; // test block-copy: access sdrams + asrams |
|
end |
endtask // run_tests |
|
|
task prg_mc; |
begin |
wbm.wb_write(0, 0, 32'h6000_0008, `BA_MASK); // program base address register |
wbm.wb_write(0, 0, 32'h6000_0000, 32'h6000_0400); // program CSR |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0008, `BA_MASK); |
wbm.wb_cmp(0, 0, 32'h6000_0000, 32'h6000_0400); |
end |
endtask //prg_mc |
|
//////////////////////////////// |
// Register test |
// |
task reg_test; |
begin |
end |
endtask // reg_test |
|
|
///////////////////////// |
// include memory tests |
// |
`include "tst_sdram.v" |
`include "tst_asram.v" |
`include "tst_ssram.v" |
`include "tst_multi_mem.v" |
|
endmodule |
|
/verilog/tst_ssram.v
0,0 → 1,167
///////////////////////////////////////////////////////////////////// |
//// //// |
//// OpenCores Memory Controller Testbench //// |
//// SSRAM memory devices tests //// |
//// This file is being included by the main testbench //// |
//// //// |
//// Author: Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// //// |
//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2001, 2002 Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
// CVS Log |
// |
// $Id: tst_ssram.v,v 1.1 2002-03-06 15:10:34 rherveille Exp $ |
// |
// $Date: 2002-03-06 15:10:34 $ |
// $Revision: 1.1 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
|
|
//////////////////////////////// |
// SSRAM Sequential access test |
// |
|
// 1) Tests ssram sequential address access |
// 2) Tests page switch |
// 3) Test burst-action by filling memory backwards (high addresses first) |
task tst_ssram_seq; |
|
parameter MAX_CYC_DELAY = 5; |
parameter MAX_STB_DELAY = 5; |
parameter SSRAM_TST_RUN = 128; |
parameter [31:0] SSRAM_TST_STARTA = `SSRAM_LOC + (SSRAM_TST_RUN<<2); |
parameter [ 7:0] SSRAM_SEL = SSRAM_TST_STARTA[28:21]; |
|
integer n, k; |
reg [31:0] my_adr, dest_adr; |
reg [31:0] my_dat; |
reg [15:0] tmp0, tmp1; |
|
// SSRAM Mode Register bits |
reg [31:0] csc_data, tms_data; |
|
integer cyc_delay, stb_delay, bl; |
|
begin |
|
$display("\n\n --- SSRAM SEQUENTIAL ACCESS TEST ---\n\n"); |
|
// clear Wishbone-Master-model current-error-counter |
wbm.set_cur_err_cnt(0); |
|
csc_data = { |
8'h00, // reserved |
SSRAM_SEL, // SEL |
4'h0, // reserved |
1'b1, // parity enabled |
1'b0, // KRO, no meaning for ssram |
1'b0, // BAS, no meaning for ssram |
1'b0, // WP |
2'b00, // MS, no meaning for ssram |
2'b10, // BW == 32bit bus. Always for ssram (maybe hardwire ???) |
3'b001, // MEM_TYPE == SDRAM |
1'b1 // EN == chip select enabled |
}; |
|
// tms_data is unused for ssrams |
tms_data = { |
32'hx |
}; |
|
// program chip select registers |
$display("\nProgramming SSRAM chip select register."); |
wbm.wb_write(0, 0, 32'h6000_0030, csc_data); // program cs4 config register (CSC4) |
|
$display("Programming SSRAM timing register."); |
wbm.wb_write(0, 0, 32'h6000_0034, tms_data); // program cs4 timing register (TMS4) |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0030, csc_data); |
wbm.wb_cmp(0, 0, 32'h6000_0034, tms_data); |
|
cyc_delay = 0; |
stb_delay = 0; |
for (cyc_delay = 0; cyc_delay <= MAX_CYC_DELAY; cyc_delay = cyc_delay +1) |
for (stb_delay = 0; stb_delay <= MAX_STB_DELAY; stb_delay = stb_delay +1) |
for (bl = 1; bl <= 8 ; bl = bl +1) |
begin |
|
$display("\nSSRAM sequential test. BL = %d, CYC-delay = %d, STB-delay = ", bl, cyc_delay, stb_delay); |
|
// fill sdrams |
$display("Filling SSRAM memory..."); |
my_dat = 0; |
for (n=0; n < SSRAM_TST_RUN; n=n+1) |
begin |
my_adr = SSRAM_TST_STARTA + ( (SSRAM_TST_RUN -n -bl) <<2); |
for (k=0; k < bl; k=k+1) |
begin |
// fill destination backwards, but with linear bursts |
dest_adr = my_adr + (k<<2); |
|
tmp0 = ~dest_adr[15:0] + bl + cyc_delay + stb_delay; |
tmp1 = dest_adr[15:0] + bl + cyc_delay + stb_delay; |
my_dat = {tmp0, tmp1}; |
|
wbm.wb_write(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
end |
|
|
// read sdrams |
$display("Verifying SSRAM memory contents..."); |
my_dat = 0; |
for (n=0; n < SSRAM_TST_RUN; n=n+1) |
begin |
my_adr = n<<2; |
dest_adr = SSRAM_TST_STARTA + my_adr; |
|
tmp0 = ~dest_adr[15:0] + bl + cyc_delay + stb_delay; |
tmp1 = dest_adr[15:0] + bl + cyc_delay + stb_delay; |
my_dat = {tmp0, tmp1}; |
|
wbm.wb_cmp(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
end |
|
repeat(10) @(posedge wb_clk); //wait a while |
|
// show Wishbone-Master-model current-error-counter |
wbm.show_cur_err_cnt; |
|
end |
endtask // test_ssram_seq |
/verilog/tst_sdram.v
0,0 → 1,1475
///////////////////////////////////////////////////////////////////// |
//// //// |
//// OpenCores Memory Controller Testbench //// |
//// SDRAM memory devices tests //// |
//// This file is being included by the main testbench //// |
//// //// |
//// Author: Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// //// |
//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2001, 2002 Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
// CVS Log |
// |
// $Id: tst_sdram.v,v 1.1 2002-03-06 15:10:34 rherveille Exp $ |
// |
// $Date: 2002-03-06 15:10:34 $ |
// $Revision: 1.1 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
|
|
//////////////////////////////// |
// SDRAM memory fill test |
// |
|
// Test memory contents overwrite |
// 1) Fill entire SDRAM memory |
// 2) Verify memory contents |
// 3) Test for BAS setting |
// |
// THIS IS A FULL MEMORY TEST |
// MAY RUN FOR A FEW DAYS |
task tst_sdram_memfill; |
parameter [31:0] SDRAM_TST_STARTA = `SDRAM1_LOC; // start at address 0 |
parameter [ 7:0] SDRAM1_SEL = SDRAM_TST_STARTA[28:21]; |
parameter SDRAM_TST_RUN = ( 1<<(`SDRAM_COLA_HI+1)<<(`SDRAM_ROWA_HI+1) ) *4; |
|
integer n; |
reg [31:0] my_adr, dest_adr; |
reg [31:0] my_dat; |
|
// config register mode bits |
reg [1:0] kro, bas; // a single register doesn't work with the for-loops |
|
// SDRAM Mode Register bits |
reg [1:0] wbl; // a single register doesn't work with the for-loops |
reg [2:0] cl, bl; |
|
reg [31:0] csc_data, tms_data; |
|
integer cyc_delay, stb_delay; |
integer bank_cnt, col_cnt; |
|
begin |
|
$display("\n\n --- SDRAM MEMORY FILL TEST ---\n\n"); |
|
// clear Wishbone-Master-model current-error-counter |
wbm.set_cur_err_cnt(0); |
|
// choose some settings, other settings will be tested |
// in next tests |
kro = 0; |
bas = 0; |
|
wbl = 0; // programmed burst length |
cl = 2; // cas latency = 2 |
bl = 2; // burst length = 4 |
|
// variables for CSC register |
for (bas = 0; bas <= 1; bas = bas +1) |
begin |
csc_data = { |
8'h00, // reserved |
SDRAM1_SEL, // SEL |
4'h0, // reserved |
1'b0, // parity disabled |
kro[0], // KRO |
bas[0], // BAS |
1'b0, // WP |
2'b10, // MS == 256MB |
2'b01, // BW == 16bit bus per device |
3'b000, // MEM_TYPE == SDRAM |
1'b1 // EN == chip select enabled |
}; |
|
tms_data = { |
4'h0, // reserved |
4'h8, // Trfc == 7 (+1) |
4'h4, // Trp == 2 (+1) ????? |
3'h3, // Trcd == 2 (+1) |
2'b11, // Twr == 2 (+1) |
5'h0, // reserved |
wbl[0], // write burst length |
2'b00, // OM == normal operation |
cl, // cas latency |
1'b0, // BT == sequential burst type |
bl |
}; |
|
// program chip select registers |
$display("\nProgramming SDRAM chip select register. KRO = %d, BAS = %d", kro, bas); |
wbm.wb_write(0, 0, 32'h6000_0028, csc_data); // program cs3 config register (CSC3) |
|
$display("Programming SDRAM timing register. WBL = %d, CL = %d, BL = %d\n", wbl, cl, bl); |
wbm.wb_write(0, 0, 32'h6000_002c, tms_data); // program cs3 timing register (TMS3) |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0028, csc_data); |
wbm.wb_cmp(0, 0, 32'h6000_002c, tms_data); |
|
// only select cyc_delay = 0 |
// only select stb_delay = 0 |
// --> fastest test_run. |
// other possibilities will be tested by next tests |
cyc_delay = 0; |
stb_delay = 0; |
|
begin |
|
// fill sdrams |
$display("Filling SDRAM memory... (This takes a while)"); |
my_dat = 0; |
bank_cnt = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = n<<2; |
dest_adr = SDRAM_TST_RUN -1 - my_adr; // fill backward |
my_dat = my_adr; |
|
if (n % (1<<(`SDRAM_COLA_HI+1)<<(`SDRAM_ROWA_HI+1)) == 0) |
begin |
col_cnt = 0; |
bank_cnt = bank_cnt +1; |
end |
|
if (n % (1<<(`SDRAM_COLA_HI+1)) == 0) |
begin |
$display("Filling bank %d, column %d", bank_cnt, col_cnt); |
col_cnt = col_cnt +1; |
end |
|
wbm.wb_write(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
|
// read sdrams |
$display("Verifying SDRAM memory contents..."); |
my_dat = 0; |
bank_cnt = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = n<<2; |
dest_adr = SDRAM_TST_STARTA + my_adr; |
my_dat = my_adr; |
|
if (n % (1<<(`SDRAM_COLA_HI+1)) == 0) |
begin |
$display("Verifying bank %d", bank_cnt); |
bank_cnt = bank_cnt +1; |
end |
|
wbm.wb_cmp(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
end |
|
repeat(10) @(posedge wb_clk); //wait a while |
end |
|
|
// show Wishbone-Master-model current-error-counter |
wbm.show_cur_err_cnt; |
|
end |
endtask // test_sdram_memfill |
|
|
//////////////////////////////// |
// SDRAM parity test |
// |
|
// 1) This is practically the 'SDRAM sequential access test' |
// 2) First check parity operation |
// 3) Then introduce some parity errors |
task tst_sdram_parity; |
|
parameter MAX_CYC_DELAY = 5; |
parameter MAX_STB_DELAY = 5; |
|
parameter [31:0] SDRAM_TST_STARTA = `SDRAM1_LOC + (1<<`SDRAM_COLA_HI) + (1<<`SDRAM_COLA_HI>>1); // start at 75% of page |
parameter [ 7:0] SDRAM1_SEL = SDRAM_TST_STARTA[28:21]; |
parameter SDRAM_TST_RUN = 16; // a few runs |
|
integer n; |
reg [31:0] my_adr, dest_adr; |
reg [31:0] my_dat; |
|
// config register mode bits |
reg [1:0] kro, bas; // a single register doesn't work with the for-loops |
|
// SDRAM Mode Register bits |
reg [1:0] wbl; // a single register doesn't work with the for-loops |
reg [2:0] cl, bl; |
|
reg [31:0] csc_data, tms_data; |
|
integer cyc_delay, stb_delay; |
|
integer mod_par; |
|
begin |
|
$display("\n\n --- SDRAM PARITY TEST ---\n\n"); |
|
// clear Wishbone-Master-model current-error-counter |
wbm.set_cur_err_cnt(0); |
|
kro = 0; |
bas = 0; |
|
wbl = 0; // programmed burst length |
cl = 2; // cas latency = 2 |
bl = 1; // burst length = 8 |
|
// simply set the parity bits to zero, when introducing parity errors |
set_par = 4'b0; |
|
// use second SDRAMS set as parity sdrams |
sel_pbus = 1; |
|
for(mod_par = 0; mod_par <= 1; mod_par = mod_par +1) |
begin |
|
// switch between parity and parity errors |
sel_par = mod_par; |
|
if(sel_par) |
$display("\n-- Checking parity generation --"); |
else |
$display("\n-- Introducing parity errors --"); |
|
// variables for TMS register |
|
// skip these settings, since they are not relevant to parity |
// for (cl = 2; cl <= 3; cl = cl +1) |
// for (wbl = 0; wbl <= 1; wbl = wbl +1) |
// for (bl = 0; bl <= 3; bl = bl +1) |
|
// variables for CSC register |
// for (kro = 0; kro <= 1; kro = kro +1) |
// for (bas = 0; bas <= 1; bas = bas +1) |
|
begin |
csc_data = { |
8'h00, // reserved |
SDRAM1_SEL, // SEL |
4'h0, // reserved |
1'b1, // parity enabled |
kro[0], // KRO |
bas[0], // BAS |
1'b0, // WP |
2'b10, // MS == 256MB |
2'b01, // BW == 16bit bus per device |
3'b000, // MEM_TYPE == SDRAM |
1'b1 // EN == chip select enabled |
}; |
|
tms_data = { |
4'h0, // reserved |
4'h8, // Trfc == 7 (+1) |
4'h4, // Trp == 2 (+1) ????? |
3'h3, // Trcd == 2 (+1) |
2'b11, // Twr == 2 (+1) |
5'h0, // reserved |
wbl[0], // write burst length |
2'b00, // OM == normal operation |
cl, // cas latency |
1'b0, // BT == sequential burst type |
bl |
}; |
|
// program chip select registers |
$display("\nProgramming SDRAM chip select register. KRO = %d, BAS = %d", kro, bas); |
wbm.wb_write(0, 0, 32'h6000_0028, csc_data); // program cs3 config register (CSC3) |
|
$display("Programming SDRAM timing register. WBL = %d, CL = %d, BL = %d\n", wbl, cl, bl); |
wbm.wb_write(0, 0, 32'h6000_002c, tms_data); // program cs3 timing register (TMS3) |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0028, csc_data); |
wbm.wb_cmp(0, 0, 32'h6000_002c, tms_data); |
|
cyc_delay = 0; |
stb_delay = 0; |
|
// skip cyc_delay and stb_delay. |
// They are not relevant to parity generation |
// for (cyc_delay = 0; cyc_delay <= MAX_CYC_DELAY; cyc_delay = cyc_delay +1) |
// for (stb_delay = 0; stb_delay <= MAX_STB_DELAY; stb_delay = stb_delay +1) |
begin |
|
$display("\nSDRAM parity test. CYC-delay = %d, STB-delay = ", cyc_delay, stb_delay); |
|
// fill sdrams |
$display("Filling SDRAM memory..."); |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = n<<2; |
dest_adr = SDRAM_TST_STARTA + my_adr; |
my_dat = my_adr + my_dat + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
wbm.wb_write(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
|
// read sdrams |
$display("Verifying SDRAM memory contents..."); |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = n<<2; |
dest_adr = SDRAM_TST_STARTA + my_adr; |
my_dat = my_adr + my_dat + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
wbm.wb_cmp(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
end |
|
repeat(10) @(posedge wb_clk); //wait a while |
end |
|
end |
|
// show Wishbone-Master-model current-error-counter |
wbm.show_cur_err_cnt; |
|
end |
endtask // test_sdram_parity |
|
//////////////////////////////// |
// SDRAM Sequential access test |
// |
|
// 1) Tests sdram sequential address access |
// 2) Tests page switch |
// 3) Tests bank-switching using BAS-bit |
// 4) Test burst-action by filling SDRAM backwards (high addresses first) |
// 5) Run test for all possible CS settings for SDRAMS |
task tst_sdram_seq; |
|
parameter MAX_CYC_DELAY = 5; |
parameter MAX_STB_DELAY = 5; |
parameter [31:0] SDRAM_TST_STARTA = `SDRAM1_LOC + (1<<`SDRAM_COLA_HI) + (1<<`SDRAM_COLA_HI>>1); // start at 75% of page |
parameter [ 7:0] SDRAM1_SEL = SDRAM_TST_STARTA[28:21]; |
parameter SDRAM_TST_RUN = (1<<`SDRAM_COLA_HI>>1); // run for half page length |
|
integer n, k; |
reg [31:0] my_adr, dest_adr; |
reg [31:0] my_dat; |
reg [15:0] tmp0, tmp1; |
|
// config register mode bits |
reg [1:0] kro, bas; // a single register doesn't work with the for-loops |
|
// SDRAM Mode Register bits |
reg [1:0] wbl; // a single register doesn't work with the for-loops |
reg [2:0] cl, bl; |
|
reg [31:0] csc_data, tms_data; |
|
integer cyc_delay, stb_delay; |
|
begin |
|
$display("\n\n --- SDRAM SEQUENTIAL ACCESS TEST ---\n\n"); |
|
// clear Wishbone-Master-model current-error-counter |
wbm.set_cur_err_cnt(0); |
|
kro = 0; |
bas = 0; |
|
wbl = 0; // programmed burst length |
cl = 2; // cas latency = 2 |
bl = 2; // burst length |
|
// variables for TMS register |
for (cl = 2; cl <= 3; cl = cl +1) |
for (wbl = 0; wbl <= 1; wbl = wbl +1) |
for (bl = 0; bl <= 3; bl = bl +1) |
|
// variables for CSC register |
for (kro = 0; kro <= 1; kro = kro +1) |
for (bas = 0; bas <= 1; bas = bas +1) |
begin |
csc_data = { |
8'h00, // reserved |
SDRAM1_SEL, // SEL |
4'h0, // reserved |
1'b0, // parity disabled |
kro[0], // KRO |
bas[0], // BAS |
1'b0, // WP |
2'b10, // MS == 256MB |
2'b01, // BW == 16bit bus per device |
3'b000, // MEM_TYPE == SDRAM |
1'b1 // EN == chip select enabled |
}; |
|
tms_data = { |
4'h0, // reserved |
4'h8, // Trfc == 7 (+1) |
4'h4, // Trp == 2 (+1) ????? |
3'h3, // Trcd == 2 (+1) |
2'b11, // Twr == 2 (+1) |
5'h0, // reserved |
wbl[0], // write burst length |
2'b00, // OM == normal operation |
cl, // cas latency |
1'b0, // BT == sequential burst type |
bl |
}; |
|
// program chip select registers |
$display("\nProgramming SDRAM chip select register. KRO = %d, BAS = %d", kro, bas); |
wbm.wb_write(0, 0, 32'h6000_0028, csc_data); // program cs3 config register (CSC3) |
|
$display("Programming SDRAM timing register. WBL = %d, CL = %d, BL = %d\n", wbl, cl, bl); |
wbm.wb_write(0, 0, 32'h6000_002c, tms_data); // program cs3 timing register (TMS3) |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0028, csc_data); |
wbm.wb_cmp(0, 0, 32'h6000_002c, tms_data); |
|
cyc_delay = 0; |
stb_delay = 0; |
for (cyc_delay = 0; cyc_delay <= MAX_CYC_DELAY; cyc_delay = cyc_delay +1) |
for (stb_delay = 0; stb_delay <= MAX_STB_DELAY; stb_delay = stb_delay +1) |
begin |
|
$display("\nSDRAM sequential test. CYC-delay = %d, STB-delay = ", cyc_delay, stb_delay); |
|
// fill sdrams |
$display("Filling SDRAM memory..."); |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+(1<<bl) ) |
begin |
my_adr = SDRAM_TST_STARTA +( (SDRAM_TST_RUN -n -(1<<bl)) <<2); |
for (k=0; k < (1<<bl); k=k+1) |
begin |
// fill destination backwards, but with linear bursts |
dest_adr = my_adr + (k<<2); |
|
tmp0 = ~dest_adr[15:0] + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
tmp1 = dest_adr[15:0] + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
my_dat = {tmp0, tmp1}; |
|
wbm.wb_write(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
end |
|
|
// read sdrams |
$display("Verifying SDRAM memory contents..."); |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = n<<2; |
dest_adr = SDRAM_TST_STARTA + my_adr; |
|
tmp0 = ~dest_adr[15:0] + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
tmp1 = dest_adr[15:0] + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
my_dat = {tmp0, tmp1}; |
|
wbm.wb_cmp(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
end |
|
repeat(10) @(posedge wb_clk); //wait a while |
end |
|
|
// show Wishbone-Master-model current-error-counter |
wbm.show_cur_err_cnt; |
|
end |
endtask // test_sdram_seq |
|
|
///////////////////////////// |
// SDRAM Random access test |
// |
|
// 1) Tests sdram random address access |
// 2) Run test for all possible CS settings for SDRAMS |
task tst_sdram_rnd; |
|
parameter MAX_CYC_DELAY = 5; |
parameter MAX_STB_DELAY = 5; |
|
parameter [31:0] SDRAM_TST_STARTA = `SDRAM1_LOC; // start somewhere in memory |
parameter [ 7:0] SDRAM1_SEL = SDRAM_TST_STARTA[28:21]; |
parameter SDRAM_TST_RUN = 64; // run a few accesses |
|
integer n; |
reg [31:0] my_adr, dest_adr; |
reg [31:0] my_dat; |
|
// config register mode bits |
reg [1:0] kro, bas; // a single register doesn't work with the for-loops |
|
// SDRAM Mode Register bits |
reg [1:0] wbl; // a single register doesn't work with the for-loops |
reg [2:0] cl, bl; |
|
reg [31:0] csc_data, tms_data; |
|
integer cyc_delay, stb_delay; |
|
begin |
|
$display("\n\n --- SDRAM RANDOM ACCESS TEST ---\n\n"); |
|
// clear Wishbone-Master-model current-error-counter |
wbm.set_cur_err_cnt(0); |
|
kro = 0; |
bas = 0; |
|
wbl = 0; // programmed burst length |
cl = 2; // cas latency = 2 |
bl = 2; // burst length = 4 |
|
// variables for TMS register |
for (cl = 2; cl <= 3; cl = cl +1) |
for (wbl = 0; wbl <= 1; wbl = wbl +1) |
for (bl = 0; bl <= 3; bl = bl +1) |
|
// variables for CSC register |
for (kro = 0; kro <= 1; kro = kro +1) |
for (bas = 0; bas <= 1; bas = bas +1) |
begin |
csc_data = { |
8'h00, // reserved |
SDRAM1_SEL, // SEL |
4'h0, // reserved |
1'b0, // parity disabled |
kro[0], // KRO |
bas[0], // BAS |
1'b0, // WP |
2'b10, // MS == 256MB |
2'b01, // BW == 16bit bus per device |
3'b000, // MEM_TYPE == SDRAM |
1'b1 // EN == chip select enabled |
}; |
|
tms_data = { |
4'h0, // reserved |
4'h8, // Trfc == 7 (+1) |
4'h4, // Trp == 2 (+1) ????? |
3'h3, // Trcd == 2 (+1) |
2'b11, // Twr == 2 (+1) |
5'h0, // reserved |
wbl[0], // write burst length |
2'b00, // OM == normal operation |
cl, // cas latency |
1'b0, // BT == sequential burst type |
bl |
}; |
|
// program chip select registers |
$display("\nProgramming SDRAM chip select register. KRO = %d, BAS = %d", kro, bas); |
wbm.wb_write(0, 0, 32'h6000_0028, csc_data); // program cs3 config register (CSC3) |
|
$display("\nProgramming SDRAM timing register. WBL = %d, CL = %d, BL = %d\n", wbl, cl, bl); |
wbm.wb_write(0, 0, 32'h6000_002c, tms_data); // program cs3 timing register (TMS3) |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0028, csc_data); |
wbm.wb_cmp(0, 0, 32'h6000_002c, tms_data); |
|
// random access requires CYC signal to be broken up (delay >= 1) |
// otherwise MemoryController expects sequential burst |
cyc_delay = 1; |
stb_delay = 0; |
for (cyc_delay = 1; cyc_delay <= MAX_CYC_DELAY; cyc_delay = cyc_delay +1) |
for (stb_delay = 0; stb_delay <= MAX_STB_DELAY; stb_delay = stb_delay +1) |
begin |
|
$display("\nSDRAM random test. CYC-delay = %d, STB-delay = ", cyc_delay, stb_delay); |
|
// fill sdrams |
$display("Filling SDRAM memory..."); |
my_adr = 0; |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = (n << 2) + my_adr; |
dest_adr = SDRAM_TST_STARTA + my_adr; |
my_dat = my_adr + my_dat + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
wbm.wb_write(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
|
// read sdrams |
$display("Verifying SDRAM memory contents...\n"); |
my_adr = 0; |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = (n << 2) + my_adr; |
dest_adr = SDRAM_TST_STARTA + my_adr; |
my_dat = my_adr + my_dat + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
wbm.wb_cmp(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
end |
end |
|
// show Wishbone-Master-model current-error-counter |
wbm.show_cur_err_cnt; |
|
end |
endtask //tst_sdram_rnd |
|
|
///////////////////////// |
// SDRAM seq RMW test |
// |
|
// 1) Tests sdram RMW cycle using sequential address accesses |
// 2) Run test for all possible CS settings for SDRAMS |
task tst_sdram_rmw_seq; |
|
parameter MAX_CYC_DELAY = 5; |
parameter MAX_STB_DELAY = 5; |
|
parameter [31:0] SDRAM_TST_STARTA = `SDRAM1_LOC; // start somewhere in memory (at dword boundary) |
parameter [ 7:0] SDRAM1_SEL = SDRAM_TST_STARTA[28:21]; |
parameter SDRAM_TST_RUN = 64; // only do a few runs |
|
integer n; |
reg [31:0] my_adr, dest_adr; |
reg [31:0] my_dat; |
|
// config register mode bits |
reg [1:0] kro, bas; // a single register doesn't work with the for-loops |
|
// SDRAM Mode Register bits |
reg [1:0] wbl; // a single register doesn't work with the for-loops |
reg [2:0] cl, bl; |
|
reg [31:0] csc_data, tms_data; |
|
integer cyc_delay, stb_delay; |
|
begin |
|
$display("\n\n --- SDRAM SEQUENTIAL ACCESS READ-MODIFY-WRITE TEST ---\n\n"); |
|
// clear Wishbone-Master-model current-error-counter |
wbm.set_cur_err_cnt(0); |
|
kro = 0; |
bas = 0; |
|
wbl = 0; // programmed burst length |
cl = 2; // cas latency = 2 |
bl = 1; // burst length = 4 |
|
// variables for TMS register |
for (cl = 2; cl <= 3; cl = cl +1) |
for (wbl = 0; wbl <= 1; wbl = wbl +1) |
for (bl = 0; bl <= 3; bl = bl +1) |
|
// variables for CSC register |
for (kro = 0; kro <= 1; kro = kro +1) |
for (bas = 0; bas <= 1; bas = bas +1) |
begin |
csc_data = { |
8'h00, // reserved |
SDRAM1_SEL, // SEL |
4'h0, // reserved |
1'b0, // parity disabled |
kro[0], // KRO |
bas[0], // BAS |
1'b0, // WP |
2'b10, // MS == 256MB |
2'b01, // BW == 16bit bus per device |
3'b000, // MEM_TYPE == SDRAM |
1'b1 // EN == chip select enabled |
}; |
|
tms_data = { |
4'h0, // reserved |
4'h8, // Trfc == 7 (+1) |
4'h4, // Trp == 2 (+1) ????? |
3'h3, // Trcd == 2 (+1) |
2'b11, // Twr == 2 (+1) |
5'h0, // reserved |
wbl[0], // write burst length |
2'b00, // OM == normal operation |
cl, // cas latency |
1'b0, // BT == sequential burst type |
bl |
}; |
|
// program chip select registers |
$display("\nProgramming SDRAM chip select register. KRO = %d, BAS = %d", kro, bas); |
wbm.wb_write(0, 0, 32'h6000_0028, csc_data); // program cs3 config register (CSC3) |
|
$display("\nProgramming SDRAM timing register. WBL = %d, CL = %d, BL = %d\n", wbl, cl, bl); |
wbm.wb_write(0, 0, 32'h6000_002c, tms_data); // program cs3 timing register (TMS3) |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0028, csc_data); |
wbm.wb_cmp(0, 0, 32'h6000_002c, tms_data); |
|
cyc_delay = 1; |
stb_delay = 0; |
for (cyc_delay = 0; cyc_delay <= MAX_CYC_DELAY; cyc_delay = cyc_delay +1) |
for (stb_delay = 0; stb_delay <= MAX_STB_DELAY; stb_delay = stb_delay +1) |
begin |
|
$display("\nSDRAM sequential Read-Modify-Write test. CYC-delay = %d, STB-delay = %d", cyc_delay, stb_delay); |
|
// fill sdrams |
$display("Filling SDRAM memory with initial contents ..."); |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = (n << 2); |
dest_adr = SDRAM_TST_STARTA + my_adr; |
my_dat = my_adr + my_dat + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
wbm.wb_write(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
|
// perform Read-Modify-Write cycle |
$display("Performing RMW cycle ..."); |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = (n << 2); |
dest_adr = SDRAM_TST_STARTA + my_adr; |
|
// read memory contents |
wbm.wb_read(cyc_delay, stb_delay, dest_adr, my_dat); |
|
// modify memory contents |
my_dat = my_dat +1; |
|
// write contents back into memory |
wbm.wb_write(cyc_delay, stb_delay, dest_adr, my_dat); |
|
end |
|
// read sdrams |
$display("Verifying SDRAM memory contents..."); |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = (n << 2); |
dest_adr = SDRAM_TST_STARTA + my_adr; |
my_dat = my_adr + my_dat + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
wbm.wb_cmp(cyc_delay, stb_delay, dest_adr, my_dat +1); |
end |
end |
end |
|
// show Wishbone-Master-model current-error-counter |
wbm.show_cur_err_cnt; |
|
end |
endtask //tst_sdram_rmw_seq |
|
///////////////////////// |
// SDRAM Random RMW test |
// |
|
// 1) Tests sdram RMW cycle using random address accesses |
// 2) Run test for all possible CS settings for SDRAMS |
task tst_sdram_rmw_rnd; |
|
parameter MAX_CYC_DELAY = 5; |
parameter MAX_STB_DELAY = 5; |
|
parameter [31:0] SDRAM_TST_STARTA = `SDRAM1_LOC; // start somewhere in memory |
parameter [ 7:0] SDRAM1_SEL = SDRAM_TST_STARTA[28:21]; |
parameter SDRAM_TST_RUN = 64; // only do a few runs |
|
integer n; |
reg [31:0] my_adr, dest_adr; |
reg [31:0] my_dat; |
|
// config register mode bits |
reg [1:0] kro, bas; // a single register doesn't work with the for-loops |
|
// SDRAM Mode Register bits |
reg [1:0] wbl; // a single register doesn't work with the for-loops |
reg [2:0] cl, bl; |
|
reg [31:0] csc_data, tms_data; |
|
integer cyc_delay, stb_delay; |
|
begin |
|
$display("\n\n --- SDRAM RANDOM ACCESS READ-MODIFY-WRITE TEST ---\n\n"); |
|
// clear Wishbone-Master-model current-error-counter |
wbm.set_cur_err_cnt(0); |
|
kro = 0; |
bas = 0; |
|
wbl = 0; // programmed burst length |
cl = 2; // cas latency = 2 |
bl = 2; // burst length = 4 |
|
// variables for TMS register |
for (cl = 2; cl <= 3; cl = cl +1) |
for (wbl = 0; wbl <= 1; wbl = wbl +1) |
for (bl = 0; bl <= 3; bl = bl +1) |
|
// variables for CSC register |
for (kro = 0; kro <= 1; kro = kro +1) |
for (bas = 0; bas <= 1; bas = bas +1) |
begin |
csc_data = { |
8'h00, // reserved |
SDRAM1_SEL, // SEL |
4'h0, // reserved |
1'b0, // parity disabled |
kro[0], // KRO |
bas[0], // BAS |
1'b0, // WP |
2'b10, // MS == 256MB |
2'b01, // BW == 16bit bus per device |
3'b000, // MEM_TYPE == SDRAM |
1'b1 // EN == chip select enabled |
}; |
|
tms_data = { |
4'h0, // reserved |
4'h8, // Trfc == 7 (+1) |
4'h4, // Trp == 2 (+1) ????? |
3'h3, // Trcd == 2 (+1) |
2'b11, // Twr == 2 (+1) |
5'h0, // reserved |
wbl[0], // write burst length |
2'b00, // OM == normal operation |
cl, // cas latency |
1'b0, // BT == sequential burst type |
bl |
}; |
|
// program chip select registers |
$display("\nProgramming SDRAM chip select register. KRO = %d, BAS = %d", kro, bas); |
wbm.wb_write(0, 0, 32'h6000_0028, csc_data); // program cs3 config register (CSC3) |
|
$display("\nProgramming SDRAM timing register. WBL = %d, CL = %d, BL = %d\n", wbl, cl, bl); |
wbm.wb_write(0, 0, 32'h6000_002c, tms_data); // program cs3 timing register (TMS3) |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0028, csc_data); |
wbm.wb_cmp(0, 0, 32'h6000_002c, tms_data); |
|
// random access requires CYC signal to be broken up (delay >= 1) |
// otherwise MemoryController expects sequential burst |
cyc_delay = 1; |
stb_delay = 0; |
for (cyc_delay = 1; cyc_delay <= MAX_CYC_DELAY; cyc_delay = cyc_delay +1) |
for (stb_delay = 0; stb_delay <= MAX_STB_DELAY; stb_delay = stb_delay +1) |
begin |
|
$display("\nSDRAM random Read-Modify-Write test. CYC-delay = %d, STB-delay = %d", cyc_delay, stb_delay); |
|
// fill sdrams |
$display("Filling SDRAM memory with initial contents ..."); |
my_adr = 0; |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = (n << 2) + my_adr; |
dest_adr = SDRAM_TST_STARTA + my_adr; |
my_dat = my_adr + my_dat + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
wbm.wb_write(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
|
// perform Read-Modify-Write cycle |
$display("Performing RMW cycle ..."); |
my_adr = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = (n << 2) + my_adr; |
dest_adr = SDRAM_TST_STARTA + my_adr; |
|
// read memory contents |
wbm.wb_read(cyc_delay, stb_delay, dest_adr, my_dat); |
|
// modify memory contents |
my_dat = my_dat +1; |
|
// write contents back into memory |
wbm.wb_write(cyc_delay, stb_delay, dest_adr, my_dat); |
|
end |
|
// read sdrams |
$display("Verifying SDRAM memory contents..."); |
my_adr = 0; |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = (n << 2) + my_adr; |
dest_adr = SDRAM_TST_STARTA + my_adr; |
my_dat = my_adr + my_dat + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
wbm.wb_cmp(cyc_delay, stb_delay, dest_adr, my_dat +1); |
end |
end |
end |
|
// show Wishbone-Master-model current-error-counter |
wbm.show_cur_err_cnt; |
|
end |
endtask //tst_sdram_rmw_rnd |
|
|
////////////////////////// |
// SDRAM Block copy test1 |
// |
|
// 1) Copy block of memory inside same memory block (chip select) |
// 2) Run test for all possible CS settings for SDRAM |
task tst_sdram_blk_cpy1; |
|
parameter MAX_CYC_DELAY = 5; |
parameter MAX_STB_DELAY = 5; |
|
parameter [31:0] SDRAM1_STARTA = `SDRAM1_LOC; |
parameter [ 7:0] SDRAM1_SEL = SDRAM1_STARTA[28:21]; |
parameter SDRAM_TST_RUN = 64; // only do a few runs |
|
parameter MAX_BSIZE = 8; |
|
parameter SDRAM_SRC = SDRAM1_STARTA; |
parameter SDRAM_DST = SDRAM1_STARTA + 32'h0001_0000; |
|
integer n, wcnt, bsize; |
reg [31:0] my_adr, src_adr, dest_adr; |
reg [31:0] my_dat; |
reg [31:0] tmp [MAX_BSIZE -1 :0]; |
|
// config register mode bits |
reg [1:0] kro, bas; // a single register doesn't work with the for-loops |
|
// SDRAM Mode Register bits |
reg [1:0] wbl; // a single register doesn't work with the for-loops |
reg [2:0] cl, bl; |
|
reg [31:0] csc_data, tms_data; |
|
integer cyc_delay, stb_delay; |
|
begin |
|
$display("\n\n --- SDRAM block copy TEST-1- ---\n\n"); |
|
// clear Wishbone-Master-model current-error-counter |
wbm.set_cur_err_cnt(0); |
|
kro = 0; |
bas = 0; |
|
wbl = 0; // programmed burst length |
cl = 2; // cas latency = 2 |
bl = 1; // burst length = 4 |
|
// variables for TMS register |
for (cl = 2; cl <= 3; cl = cl +1) |
for (wbl = 0; wbl <= 1; wbl = wbl +1) |
for (bl = 0; bl <= 3; bl = bl +1) |
|
// variables for CSC register |
for (kro = 0; kro <= 1; kro = kro +1) |
for (bas = 0; bas <= 1; bas = bas +1) |
begin |
csc_data = { |
8'h00, // reserved |
SDRAM1_SEL, // SEL |
4'h0, // reserved |
1'b0, // parity disabled |
kro[0], // KRO |
bas[0], // BAS |
1'b0, // WP |
2'b10, // MS == 256MB |
2'b01, // BW == 16bit bus per device |
3'b000, // MEM_TYPE == SDRAM |
1'b1 // EN == chip select enabled |
}; |
|
tms_data = { |
4'h0, // reserved |
4'h8, // Trfc == 7 (+1) |
4'h4, // Trp == 2 (+1) ????? |
3'h3, // Trcd == 2 (+1) |
2'b11, // Twr == 2 (+1) |
5'h0, // reserved |
wbl[0], // write burst length |
2'b00, // OM == normal operation |
cl, // cas latency |
1'b0, // BT == sequential burst type |
bl |
}; |
|
// program chip select registers |
$display("\nProgramming SDRAM chip select register. KRO = %d, BAS = %d", kro, bas); |
wbm.wb_write(0, 0, 32'h6000_0028, csc_data); // program cs3 config register (CSC3) |
|
$display("Programming SDRAM timing register. WBL = %d, CL = %d, BL = %d\n", wbl, cl, bl); |
wbm.wb_write(0, 0, 32'h6000_002c, tms_data); // program cs3 timing register (TMS3) |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0028, csc_data); |
wbm.wb_cmp(0, 0, 32'h6000_002c, tms_data); |
|
cyc_delay = 0; |
stb_delay = 0; |
bsize = 2; |
wcnt = 0; |
for (cyc_delay = 0; cyc_delay <= MAX_CYC_DELAY; cyc_delay = cyc_delay +1) |
for (stb_delay = 0; stb_delay <= MAX_STB_DELAY; stb_delay = stb_delay +1) |
for (bsize = 0; bsize < MAX_BSIZE; bsize = bsize +1) |
begin |
|
if (cyc_delay == 0) |
while ( ((bsize +1) % (1 << bl) != 0) && (bsize < (MAX_BSIZE -1)) ) |
bsize = bsize +1; |
|
$display("Block copy test-1-. CYC-delay = %d, STB-delay = %d, burst-size = %d", cyc_delay, stb_delay, bsize); |
|
// fill sdrams |
my_dat = 0; |
for (n = 0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = (n << 2); |
dest_adr = SDRAM_SRC + my_adr; |
my_dat = my_adr + my_dat + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
wbm.wb_write(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
|
// perform Read-Modify-Write cycle |
n = 0; |
while (n < SDRAM_TST_RUN) |
begin |
// read data from sdrams |
for (wcnt = 0; wcnt <= bsize; wcnt = wcnt +1) |
begin |
my_adr = (n + wcnt) << 2; |
src_adr = SDRAM_SRC + my_adr; |
|
// read memory contents |
wbm.wb_read(cyc_delay, stb_delay, src_adr, my_dat); |
|
// modify memory contents |
tmp[wcnt] = my_dat +1; |
end |
|
// copy data into sdrams; new location |
for (wcnt = 0; wcnt <= bsize; wcnt = wcnt +1) |
begin |
my_adr = (n + wcnt) << 2; |
dest_adr = SDRAM_DST + my_adr; |
|
// write contents back into memory |
wbm.wb_write(cyc_delay, stb_delay, dest_adr, tmp[wcnt]); |
end |
|
n = n + bsize +1; |
end |
|
// read sdrams |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = (n << 2); |
dest_adr = SDRAM_DST + my_adr; |
my_dat = my_adr + my_dat + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
wbm.wb_cmp(cyc_delay, stb_delay, dest_adr, my_dat +1); |
end |
end |
end |
|
// show Wishbone-Master-model current-error-counter |
wbm.show_cur_err_cnt; |
|
$display("\nSDRAM block copy test-1- ended"); |
|
end |
endtask // tst_sdram_blk_cpy1 |
|
|
|
////////////////////////// |
// SDRAM Block copy test2 |
// |
|
// 1) Copy a modified block of memory to the same memory location |
// 2) Run test for all possible CS settings for SDRAM |
task tst_sdram_blk_cpy2; |
|
parameter MAX_CYC_DELAY = 5; |
parameter MAX_STB_DELAY = 5; |
|
parameter [31:0] SDRAM1_STARTA = `SDRAM1_LOC; |
parameter [ 7:0] SDRAM1_SEL = SDRAM1_STARTA[28:21]; |
|
parameter SDRAM_TST_RUN = 64; // only do a few runs |
|
parameter MAX_BSIZE = 8; |
|
parameter SDRAM_SRC = SDRAM1_STARTA; |
|
integer n, wcnt, bsize; |
reg [31:0] my_adr, src_adr, dest_adr; |
reg [31:0] my_dat; |
reg [31:0] tmp [MAX_BSIZE -1 :0]; |
|
// config register mode bits |
reg [1:0] kro, bas; // a single register doesn't work with the for-loops |
|
// SDRAM Mode Register bits |
reg [1:0] wbl; // a single register doesn't work with the for-loops |
reg [2:0] cl, bl; |
|
reg [31:0] csc_data, tms_data; |
|
integer cyc_delay, stb_delay; |
|
begin |
|
$display("\n\n --- SDRAM block copy TEST-2- ---\n\n"); |
|
// clear Wishbone-Master-model current-error-counter |
wbm.set_cur_err_cnt(0); |
|
kro = 0; |
bas = 0; |
|
wbl = 0; // programmed burst length |
cl = 2; // cas latency = 2 |
bl = 1; // burst length = 4 |
|
// variables for TMS register |
for (cl = 2; cl <= 3; cl = cl +1) |
for (wbl = 0; wbl <= 1; wbl = wbl +1) |
for (bl = 0; bl <= 3; bl = bl +1) |
|
// variables for CSC register |
for (kro = 0; kro <= 1; kro = kro +1) |
for (bas = 0; bas <= 1; bas = bas +1) |
begin |
csc_data = { |
8'h00, // reserved |
SDRAM1_SEL, // SEL |
4'h0, // reserved |
1'b0, // parity disabled |
kro[0], // KRO |
bas[0], // BAS |
1'b0, // WP |
2'b10, // MS == 256MB |
2'b01, // BW == 16bit bus per device |
3'b000, // MEM_TYPE == SDRAM |
1'b1 // EN == chip select enabled |
}; |
|
tms_data = { |
4'h0, // reserved |
4'h8, // Trfc == 7 (+1) |
4'h4, // Trp == 2 (+1) ????? |
3'h3, // Trcd == 2 (+1) |
2'b11, // Twr == 2 (+1) |
5'h0, // reserved |
wbl[0], // write burst length |
2'b00, // OM == normal operation |
cl, // cas latency |
1'b0, // BT == sequential burst type |
bl |
}; |
|
// program chip select registers |
$display("\nProgramming SDRAM chip select register. KRO = %d, BAS = %d", kro, bas); |
wbm.wb_write(0, 0, 32'h6000_0028, csc_data); // program cs3 config register (CSC3) |
|
$display("Programming SDRAM timing register. WBL = %d, CL = %d, BL = %d\n", wbl, cl, bl); |
wbm.wb_write(0, 0, 32'h6000_002c, tms_data); // program cs3 timing register (TMS3) |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0028, csc_data); |
wbm.wb_cmp(0, 0, 32'h6000_002c, tms_data); |
|
cyc_delay = 0; |
stb_delay = 0; |
bsize = 2; |
wcnt = 0; |
for (cyc_delay = 0; cyc_delay <= MAX_CYC_DELAY; cyc_delay = cyc_delay +1) |
for (stb_delay = 0; stb_delay <= MAX_STB_DELAY; stb_delay = stb_delay +1) |
for (bsize = 0; bsize < MAX_BSIZE; bsize = bsize +1) |
begin |
|
if (cyc_delay == 0) |
while ( ((bsize +1) % (1 << bl) != 0) && (bsize < (MAX_BSIZE -1)) ) |
bsize = bsize +1; |
|
$display("Block copy test-2-. CYC-delay = %d, STB-delay = %d, burst-size = %d", cyc_delay, stb_delay, bsize); |
|
// fill sdrams |
my_dat = 0; |
for (n = 0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = (n << 2); |
dest_adr = SDRAM_SRC + my_adr; |
my_dat = my_adr + my_dat + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
wbm.wb_write(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
|
// perform Read-Modify-Write cycle |
n = 0; |
while (n < SDRAM_TST_RUN) |
begin |
// read data from sdrams |
for (wcnt = 0; wcnt <= bsize; wcnt = wcnt +1) |
begin |
my_adr = (n + wcnt) << 2; |
src_adr = SDRAM_SRC + my_adr; |
|
// read memory contents |
wbm.wb_read(cyc_delay, stb_delay, src_adr, my_dat); |
|
// modify memory contents |
tmp[wcnt] = my_dat +1; |
end |
|
// copy data into sdrams; new location |
for (wcnt = 0; wcnt <= bsize; wcnt = wcnt +1) |
begin |
my_adr = (n + wcnt) << 2; |
dest_adr = SDRAM_SRC + my_adr; |
|
// write contents back into memory |
wbm.wb_write(cyc_delay, stb_delay, dest_adr, tmp[wcnt]); |
end |
|
n = n + bsize +1; |
end |
|
// read sdrams |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = (n << 2); |
dest_adr = SDRAM_SRC + my_adr; |
my_dat = my_adr + my_dat + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
wbm.wb_cmp(cyc_delay, stb_delay, dest_adr, my_dat +1); |
end |
end |
end |
|
// show Wishbone-Master-model current-error-counter |
wbm.show_cur_err_cnt; |
|
$display("\nSDRAM block copy test-2- ended"); |
|
end |
endtask // tst_sdram_blk_cpy |
|
|
///////////////////////////// |
// SDRAM byte access test |
// |
|
// 1) Test byte/word writes (SDRAM DQM lines) |
// 2) Run for all CS settings for SDRAMS |
// 3) This test also checks the parity bits |
task tst_sdram_bytes; |
|
parameter MAX_CYC_DELAY = 5; |
parameter MAX_STB_DELAY = 5; |
|
parameter SDRAM_TST_STARTA = `SDRAM1_LOC; // start at address 0 |
parameter [7:0] SDRAM1_SEL = SDRAM_TST_STARTA[28:21]; |
parameter SDRAM_TST_RUN = 64; // only do a few runs |
|
integer n; |
reg [31:0] my_adr, dest_adr; |
reg [31:0] my_dat; |
|
// config register mode bits |
reg [1:0] kro, bas; // a single register doesn't work with the for-loops |
|
// SDRAM Mode Register bits |
reg [1:0] wbl; // a single register doesn't work with the for-loops |
reg [2:0] cl, bl; |
|
reg [31:0] csc_data, tms_data; |
|
integer sel; |
integer cyc_delay, stb_delay; |
|
begin |
|
$display("\n\n --- SDRAM BYTE ACCESS TEST ---\n\n"); |
|
// clear Wishbone-Master-model current-error-counter |
wbm.set_cur_err_cnt(0); |
|
// use second SDRAMS set as parity sdrams |
sel_pbus = 1; |
|
// choose some default settings |
kro = 0; |
bas = 0; |
|
wbl = 0; // programmed burst length |
cl = 2; // cas latency = 2 |
bl = 2; // burst length = 4 |
|
// variables for TMS register |
for (cl = 2; cl <= 3; cl = cl +1) |
for (wbl = 0; wbl <= 1; wbl = wbl +1) |
for (bl = 0; bl <= 3; bl = bl +1) |
|
// variables for CSC register |
for (kro = 0; kro <= 1; kro = kro +1) |
// for (bas = 0; bas <= 1; bas = bas +1) // ignore BAS for this test |
begin |
csc_data = { |
8'h00, // reserved |
SDRAM1_SEL, // SEL |
4'h0, // reserved |
1'b1, // parity enabled |
kro[0], // KRO |
bas[0], // BAS |
1'b0, // WP |
2'b10, // MS == 256MB |
2'b01, // BW == 16bit bus per device |
3'b000, // MEM_TYPE == SDRAM |
1'b1 // EN == chip select enabled |
}; |
|
tms_data = { |
4'h0, // reserved |
4'h8, // Trfc == 7 (+1) |
4'h4, // Trp == 2 (+1) ????? |
3'h3, // Trcd == 2 (+1) |
2'b11, // Twr == 2 (+1) |
5'h0, // reserved |
wbl[0], // write burst length |
2'b00, // OM == normal operation |
cl, // cas latency |
1'b0, // BT == sequential burst type |
bl |
}; |
|
// program chip select registers |
$display("\nProgramming SDRAM chip select register. KRO = %d, BAS = %d", kro, bas); |
wbm.wb_write(0, 0, 32'h6000_0028, csc_data); // program cs3 config register (CSC3) |
|
$display("\nProgramming SDRAM timing register. WBL = %d, CL = %d, BL = %d\n", wbl, cl, bl); |
wbm.wb_write(0, 0, 32'h6000_002c, tms_data); // program cs3 timing register (TMS3) |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0028, csc_data); |
wbm.wb_cmp(0, 0, 32'h6000_002c, tms_data); |
|
cyc_delay = 1; |
stb_delay = 0; |
for (cyc_delay = 1; cyc_delay <= MAX_CYC_DELAY; cyc_delay = cyc_delay +1) |
for (stb_delay = 0; stb_delay <= MAX_STB_DELAY; stb_delay = stb_delay +1) |
begin |
|
$display("\nSDRAM byte test. CYC-delay = %d, STB-delay = ", cyc_delay, stb_delay); |
|
// fill sdrams |
$display("Filling SDRAM memory..."); |
my_adr = 0; |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = (n << 2); |
dest_adr = SDRAM_TST_STARTA + my_adr; |
my_dat = my_adr + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
my_dat = {my_dat[7:0] +8'd3, my_dat[7:0] +8'd2, my_dat[7:0] +8'd1, my_dat[7:0]}; |
|
wbm.wb_write(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
|
// switch memory contents |
$display("Swapping bytes..."); |
my_adr = 0; |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
for (sel=0; sel < 16; sel=sel+1) |
begin |
my_adr = (n << 2); |
dest_adr = SDRAM_TST_STARTA + my_adr; |
wbm.wb_read(cyc_delay, stb_delay, dest_adr, my_dat); |
|
my_dat = {my_dat[31:24] +8'd1, my_dat[23:16] +8'd1, my_dat[15:8] +8'd1, my_dat[7:0] +8'd1}; |
wbm.wb_write_sel(cyc_delay, stb_delay, sel, dest_adr, my_dat); |
|
end |
|
// read sdrams |
$display("Verifying SDRAM memory contents..."); |
my_dat = 0; |
for (n=0; n < SDRAM_TST_RUN; n=n+1) |
begin |
my_adr = (n << 2); |
dest_adr = SDRAM_TST_STARTA + my_adr; |
my_dat = my_adr + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
my_dat = {my_dat[7:0] +8'd3, my_dat[7:0] +8'd2, my_dat[7:0] +8'd1, my_dat[7:0]}; |
my_dat = {my_dat[31:24] +8'd8, my_dat[23:16] +8'd8, my_dat[15:8] +8'd8, my_dat[7:0] +8'd8}; |
|
wbm.wb_cmp(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
end |
end |
|
// show Wishbone-Master-model current-error-counter |
wbm.show_cur_err_cnt; |
|
end |
endtask //tst_sdram_bytes |
/verilog/tst_multi_mem.v
0,0 → 1,588
///////////////////////////////////////////////////////////////////// |
//// //// |
//// OpenCores Memory Controller Testbench //// |
//// Multiple memory devices tests //// |
//// This file is being included by the main testbench //// |
//// //// |
//// Author: Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// //// |
//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2001, 2002 Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
// CVS Log |
// |
// $Id: tst_multi_mem.v,v 1.1 2002-03-06 15:10:34 rherveille Exp $ |
// |
// $Date: 2002-03-06 15:10:34 $ |
// $Revision: 1.1 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
|
/////////////////////////////// |
// SDRAM/SRAM Block copy test1 |
// |
|
// Test multi-memory accesses (SDRAM & SRAM) |
// 1) Copy memory-block from SDRAM to SRAM |
// 2) Copy block from SRAM to SDRAM |
// 3) Run test for all CS settings for SDRAMS |
task tst_blk_cpy1; |
|
parameter MAX_CYC_DELAY = 5; |
parameter MAX_STB_DELAY = 5; |
parameter MAX_BSIZE = 8; |
|
parameter [31:0] SDRAM_STARTA = `SDRAM1_LOC; |
parameter [ 7:0] SDRAM_SEL = SDRAM_STARTA[28:21]; |
parameter [31:0] SRAM_STARTA = `SRAM_LOC; |
parameter [ 7:0] SRAM_SEL = SRAM_STARTA[28:21]; |
parameter TST_RUN = 64; // only perform a few accesses |
|
parameter SDRAM_SRC = SDRAM_STARTA; |
parameter SRAM_SRC = SRAM_STARTA; |
|
integer n, wcnt, bsize; |
reg [31:0] my_adr, src_adr, dest_adr; |
reg [31:0] my_dat; |
reg [31:0] tmp [MAX_BSIZE -1 :0]; |
reg [31:0] sdram_dest; |
|
// config register mode bits |
reg [1:0] kro, bas; // a single register doesn't work with the for-loops |
|
// SDRAM Mode Register bits |
reg [1:0] wbl; // a single register doesn't work with the for-loops |
reg [2:0] cl, bl; |
|
reg [31:0] csc_data, tms_data; |
|
integer cyc_delay, stb_delay; |
|
begin |
|
$display("\n\n --- Multiple memory block copy TEST-1- ---\n\n"); |
|
// clear Wishbone-Master-model current-error-counter |
wbm.set_cur_err_cnt(0); |
|
// program asynchronous SRAMs |
csc_data = { |
8'h00, // reserved |
SRAM_SEL, // SEL base address (a[28:21] == 8'b0100_0000) |
4'h0, // reserved |
1'b0, // PEN no parity |
1'b0, // KRO --- |
1'b0, // BAS --- |
1'b0, // WP no write protection |
2'b00, // MS --- |
2'h2, // BW Bus width |
3'h2, // MEM memory type == asynchronous |
1'b1 // EN enable chip select |
}; |
|
tms_data = { |
6'h0, // reserved |
6'h0, // Twwd = 5ns => 0ns |
4'h0, // Twd = 0ns => 0ns |
4'h1, // Twpw = 15ns => 20ns |
4'h0, // Trdz = 8ns => 10ns |
8'h02 // Trdv = 20ns => 20ns |
}; |
|
// program chip select registers |
wbm.wb_write(0, 0, 32'h6000_0018, csc_data); // program cs1 config register |
wbm.wb_write(0, 0, 32'h6000_001c, tms_data); // program cs1 timing register |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0018, csc_data); |
wbm.wb_cmp(0, 0, 32'h6000_001c, tms_data); |
|
|
// SDRAMS |
kro = 1; |
bas = 1; |
|
wbl = 0; // programmed burst length |
cl = 2; // cas latency |
bl = 0; // burst length |
|
// variables for TMS register |
for (cl = 2; cl <= 3; cl = cl +1) |
for (wbl = 0; wbl <= 1; wbl = wbl +1) |
for (bl = 0; bl <= 3; bl = bl +1) |
|
// variables for CSC register |
for (kro = 0; kro <= 1; kro = kro +1) |
for (bas = 0; bas <= 1; bas = bas +1) |
begin |
csc_data = { |
8'h00, // reserved |
SDRAM_SEL, // SEL |
4'h0, // reserved |
1'b0, // parity disabled |
kro[0], // KRO |
bas[0], // BAS |
1'b0, // WP |
2'b10, // MS == 256MB |
2'b01 , // BW == 16bit bus per device |
3'b000, // MEM_TYPE == SDRAM |
1'b1 // EN == chip select enabled |
}; |
|
tms_data = { |
4'h0, // reserved |
4'h8, // Trfc == 7 (+1) |
4'h4, // Trp == 2 (+1) ????? |
3'h3, // Trcd == 2 (+1) |
2'b11, // Twr == 2 (+1) |
5'h0, // reserved |
wbl[0], // write burst length |
2'b00, // OM == normal operation |
cl, // cas latency |
1'b0, // BT == sequential burst type |
bl |
}; |
|
// program chip select registers |
$display("\nProgramming SDRAM chip select register. KRO = %d, BAS = %d", kro, bas); |
wbm.wb_write(0, 0, 32'h6000_0028, csc_data); // program cs3 config register (CSC3) |
|
$display("Programming SDRAM timing register. WBL = %d, CL = %d, BL = %d\n", wbl, cl, bl); |
wbm.wb_write(0, 0, 32'h6000_002c, tms_data); // program cs3 timing register (TMS3) |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0028, csc_data); |
wbm.wb_cmp(0, 0, 32'h6000_002c, tms_data); |
|
// calculate sdram destination address |
if (bas) |
sdram_dest = SDRAM_SRC + 32'h0001_0000; // add row address |
else |
sdram_dest = SDRAM_SRC + 32'h0000_0800; // add column address |
|
cyc_delay = 1; |
stb_delay = 2; |
bsize = 0; |
wcnt = 0; |
for (cyc_delay = 0; cyc_delay <= MAX_CYC_DELAY; cyc_delay = cyc_delay +1) |
for (stb_delay = 0; stb_delay <= MAX_STB_DELAY; stb_delay = stb_delay +1) |
for (bsize = 0; bsize < MAX_BSIZE; bsize = bsize +1) |
begin |
|
if (cyc_delay == 0) |
while ( ((bsize +1) % (1 << bl) != 0) && (bsize < (MAX_BSIZE -1)) ) |
bsize = bsize +1; |
|
$display("SDRAM/SRAM block copy test-1-. CYC-delay = %d, STB-delay = %d, burst-size = %d", cyc_delay, stb_delay, bsize); |
|
// fill sdrams |
my_dat = 0; |
for (n = 0; n < TST_RUN; n=n+1) |
begin |
my_adr = (n << 2); |
dest_adr = SDRAM_SRC + my_adr; |
my_dat = my_adr + my_dat + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
wbm.wb_write(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
|
// perform Read-Modify-Write cycle |
n = 0; |
while (n < TST_RUN) |
begin |
// copy from sdrams into srams |
for (wcnt = 0; wcnt <= bsize; wcnt = wcnt +1) |
begin |
my_adr = (n + wcnt) << 2; |
src_adr = SDRAM_SRC + my_adr; |
|
// read memory contents |
wbm.wb_read(cyc_delay, stb_delay, src_adr, my_dat); |
|
// modify memory contents |
tmp[wcnt] = my_dat +1; |
end |
|
for (wcnt = 0; wcnt <= bsize; wcnt = wcnt +1) |
begin |
my_adr = (n + wcnt) << 2; |
dest_adr = SRAM_SRC + my_adr; |
|
// write contents back into memory |
wbm.wb_write(cyc_delay, stb_delay, dest_adr, tmp[wcnt]); |
end |
|
// copy from srams into sdrams |
for (wcnt = 0; wcnt <= bsize; wcnt = wcnt +1) |
begin |
my_adr = (n + wcnt) << 2; |
src_adr = SRAM_SRC + my_adr; |
|
// read memory contents |
wbm.wb_read(cyc_delay, stb_delay, src_adr, my_dat); |
|
// modify memory contents |
tmp[wcnt] = my_dat -1; |
end |
|
for (wcnt = 0; wcnt <= bsize; wcnt = wcnt +1) |
begin |
my_adr = (n + wcnt) << 2; |
dest_adr = sdram_dest + my_adr; |
|
// write contents back into memory |
wbm.wb_write(cyc_delay, stb_delay, dest_adr, tmp[wcnt]); |
end |
|
n = n + bsize +1; |
end |
|
// read sdrams |
my_dat = 0; |
for (n=0; n < TST_RUN; n=n+1) |
begin |
my_adr = (n << 2); |
dest_adr = sdram_dest + my_adr; |
my_dat = my_adr + my_dat + kro + bas + wbl + cl + bl + cyc_delay + stb_delay; |
|
wbm.wb_cmp(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
end |
end |
|
// show Wishbone-Master-model current-error-counter |
wbm.show_cur_err_cnt; |
|
$display("\nSDRAM/SRAM block copy test-1- ended"); |
|
end |
endtask // tst_blk_cpy1 |
|
|
/////////////////////////////// |
// SDRAM/SDRAM Block copy test2 |
// |
|
// Test multimemory accesses (SDRAM & SDRAM) |
// 1) Copy memory block from SDRAM1 to SDRAM2 |
// 2) Copy block from SDRAM2 to SDRAM1 |
// 3) Use different pages/banks for copy (4 runs) |
// 4) Run test for all CS settings for SDRAM1 & SDRAM2 |
// |
// THIS IS A VERY LONG TEST !!!! |
// MAY RUN FOR A COUPLE OF WEEKS |
task tst_blk_cpy2; |
|
// if the MAX_ numbers are larger than 15, adjust the appropriate _reg registers (see below) |
parameter MAX_CYC_DELAY = 5; |
parameter MAX_STB_DELAY = 5; |
parameter MAX_BSIZE = 8; |
|
parameter [31:0] SDRAM1_STARTA = `SDRAM1_LOC; |
parameter [ 7:0] SDRAM1_SEL = SDRAM1_STARTA[28:21]; |
parameter [31:0] SDRAM2_STARTA = `SDRAM2_LOC; |
parameter [ 7:0] SDRAM2_SEL = SDRAM2_STARTA[28:21]; |
parameter TST_RUN = 32; // only perform a few accesses |
|
parameter SDRAM0 = SDRAM1_STARTA; |
parameter SDRAM1 = SDRAM2_STARTA; |
|
integer n, wcnt, bsize, opt; |
reg [31:0] my_adr, src_adr, dest_adr, dest_adr0, dest_adr1; |
reg [31:0] my_dat; |
reg [31:0] tmp [MAX_BSIZE -1 :0]; |
|
// display registers (convert integers into regs) |
reg [1:0] opt_reg; |
reg [3:0] cyc_reg, stb_reg, bsz_reg; |
|
// config register mode bits |
reg [1:0] kro0, bas0, kro1, bas1; // a single register doesn't work with the for-loops |
|
// SDRAM Mode Register bits |
reg [1:0] wbl0, wbl1; // a single register doesn't work with the for-loops |
reg [2:0] cl0, bl0, cl1, bl1; |
|
reg [31:0] csc_data, tms_data; |
|
integer cyc_delay, stb_delay; |
|
begin |
|
$display("\n\n --- Multiple memory block copy TEST-2- ---\n\n"); |
|
// clear Wishbone-Master-model current-error-counter |
wbm.set_cur_err_cnt(0); |
|
for(opt = 0; opt <= 4; opt = opt +1) |
begin |
// SDRAM1 |
kro0 = 0; |
bas0 = 0; |
|
wbl0 = 0; |
cl0 = 2; // cas latency = 2 |
bl0 = 1; |
|
// variables for TMS register |
for (cl0 = 2; cl0 <= 3; cl0 = cl0 +1) |
for (wbl0 = 0; wbl0 <= 1; wbl0 = wbl0 +1) |
for (bl0 = 0; bl0 <= 3; bl0 = bl0 +1) |
|
// variables for CSC register |
for (kro0 = 0; kro0 <= 1; kro0 = kro0 +1) |
// for (bas0 = 0; bas0 <= 1; bas0 = bas0 +1) // ignore bas, speed up test |
begin |
csc_data = { |
8'h00, // reserved |
SDRAM1_SEL, // SEL |
4'h0, // reserved |
1'b0, // parity disabled |
kro0[0], // KRO |
bas0[0], // BAS |
1'b0, // WP |
2'b10, // MS == 256MB |
2'b01, // BW == 16bit bus per device |
3'b000, // MEM_TYPE == SDRAM |
1'b1 // EN == chip select enabled |
}; |
|
tms_data = { |
4'h0, // reserved |
4'h8, // Trfc == 7 (+1) |
4'h4, // Trp == 2 (+1) ????? |
3'h3, // Trcd == 2 (+1) |
2'b11, // Twr == 2 (+1) |
5'h0, // reserved |
wbl0[0],// write burst length |
2'b00, // OM == normal operation |
cl0, // cas latency |
1'b0, // BT == sequential burst type |
bl0 // BL == burst length |
}; |
|
// program chip select registers |
$display("\nProgramming SDRAM1 chip select register. KRO = %d, BAS = %d", kro0, bas0); |
wbm.wb_write(0, 0, 32'h6000_0028, csc_data); // program cs3 config register (CSC3) |
|
$display("Programming SDRAM1 timing register. WBL = %d, CL = %d, BL = %d\n", wbl0, cl0, bl0); |
wbm.wb_write(0, 0, 32'h6000_002c, tms_data); // program cs3 timing register (TMS3) |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0028, csc_data); |
wbm.wb_cmp(0, 0, 32'h6000_002c, tms_data); |
|
// calculate sdram destination address |
if (!opt[0]) |
dest_adr0 = SDRAM0; |
else |
if (bas0) |
dest_adr0 = SDRAM0 + 32'h0001_0000; // add row address |
else |
dest_adr0 = SDRAM0 + 32'h0000_0800; // add column address |
|
//SDRAM1 |
kro1 = 0; |
bas1 = 0; |
|
wbl1 = 1; |
cl1 = 2; // cas latency = 2 |
bl1 = 2; |
|
// variables for TMS register |
for (cl1 = 2; cl1 <= 3; cl1 = cl1 +1) |
for (wbl1 = 0; wbl1 <= 1; wbl1 = wbl1 +1) |
for (bl1 = 0; bl1 <= 3; bl1 = bl1 +1) |
|
// variables for CSC register |
for (kro1 = 0; kro1 <= 1; kro1 = kro1 +1) |
// for (bas1 = 0; bas1 <= 1; bas1 = bas1 +1) // ignore bas, speed up test |
begin |
csc_data = { |
8'h00, // reserved |
SDRAM2_SEL, // SEL |
4'h0, // reserved |
1'b0, // parity disabled |
kro1[0], // KRO |
bas1[0], // BAS |
1'b0, // WP |
2'b10, // MS == 256MB |
2'b01, // BW == 16bit bus per device |
3'b000, // MEM_TYPE == SDRAM |
1'b1 // EN == chip select enabled |
}; |
|
tms_data = { |
4'h0, // reserved |
4'h8, // Trfc == 7 (+1) |
4'h4, // Trp == 2 (+1) ????? |
3'h3, // Trcd == 2 (+1) |
2'b11, // Twr == 2 (+1) |
5'h0, // reserved |
wbl1[0],// write burst length |
2'b00, // OM == normal operation |
cl1, // cas latency |
1'b0, // BT == sequential burst type |
bl1 // BL == burst length |
}; |
|
// program chip select registers |
$display("\nProgramming SDRAM2 chip select register. KRO = %d, BAS = %d", kro1, bas1); |
wbm.wb_write(0, 0, 32'h6000_0020, csc_data); // program cs3 config register (CSC2) |
|
$display("Programming SDRAM2 timing register. WBL = %d, CL = %d, BL = %d\n", wbl1, cl1, bl1); |
wbm.wb_write(0, 0, 32'h6000_0024, tms_data); // program cs3 timing register (TMS2) |
|
// check written data |
wbm.wb_cmp(0, 0, 32'h6000_0020, csc_data); |
wbm.wb_cmp(0, 0, 32'h6000_0024, tms_data); |
|
// calculate sdram destination address |
if (!opt[1]) |
dest_adr1 = SDRAM1; |
else |
if (bas1) |
dest_adr1 = SDRAM1 + 32'h0001_0000; // add row address |
else |
dest_adr1 = SDRAM1 + 32'h0000_0800; // add column address |
|
cyc_delay = 0; |
stb_delay = 0; |
bsize = 2; |
wcnt = 0; |
for (cyc_delay = 0; cyc_delay <= MAX_CYC_DELAY; cyc_delay = cyc_delay +1) |
for (stb_delay = 0; stb_delay <= MAX_STB_DELAY; stb_delay = stb_delay +1) |
for (bsize = 0; bsize < MAX_BSIZE; bsize = bsize +1) |
begin |
if (cyc_delay == 0) |
while ( ( ((bsize +1) % (1 << bl0) !=0) && ((1 << bl0) % (bsize +1) !=0) ) || |
( ((bsize +1) % (1 << bl1) !=0) && ((1 << bl1) % (bsize +1) !=0) ) |
) |
bsize = bsize +1; |
|
|
// convert integers into regs (for display) |
opt_reg = opt; |
cyc_reg = cyc_delay; |
stb_reg = stb_delay; |
bsz_reg = bsize; |
|
|
$display("SDRAM multi-memory block copy test-2-. Opt = %d, CYC-delay = %d, STB-delay = %d, burst-size = %d", opt_reg, cyc_reg, stb_reg, bsz_reg); |
|
// fill sdram0 |
my_dat = 0; |
for (n = 0; n < TST_RUN; n=n+1) |
begin |
my_adr = (n << 2); |
dest_adr = SDRAM0 + my_adr; |
my_dat = my_adr + my_dat + kro0 + kro1 + bas0 + bas1 + wbl0 + wbl1 + cl0 + cl1 + bl0 + bl1 + cyc_delay + stb_delay; |
|
wbm.wb_write(cyc_delay, stb_delay, dest_adr, my_dat); |
end |
|
// perform Read-Modify-Write cycle |
n = 0; |
while (n < TST_RUN) |
begin |
// copy from sdram0 into sdram1 |
for (wcnt = 0; wcnt <= bsize; wcnt = wcnt +1) |
begin |
my_adr = (n + wcnt) << 2; |
src_adr = SDRAM0 + my_adr; |
|
// read memory contents |
wbm.wb_read(cyc_delay, stb_delay, src_adr, my_dat); |
|
// modify memory contents |
tmp[wcnt] = my_dat +1; |
end |
|
for (wcnt = 0; wcnt <= bsize; wcnt = wcnt +1) |
begin |
my_adr = (n + wcnt) << 2; |
dest_adr = dest_adr1 + my_adr; |
|
// write contents back into memory |
wbm.wb_write(cyc_delay, stb_delay, dest_adr, tmp[wcnt]); |
end |
|
// copy from sdram1 into sdram0 |
for (wcnt = 0; wcnt <= bsize; wcnt = wcnt +1) |
begin |
my_adr = (n + wcnt) << 2; |
src_adr = dest_adr1 + my_adr; |
|
// read memory contents |
wbm.wb_read(cyc_delay, stb_delay, src_adr, my_dat); |
|
// modify memory contents |
tmp[wcnt] = my_dat +1; |
end |
|
for (wcnt = 0; wcnt <= bsize; wcnt = wcnt +1) |
begin |
my_adr = (n + wcnt) << 2; |
dest_adr = dest_adr0 + my_adr; |
|
// write contents back into memory |
wbm.wb_write(cyc_delay, stb_delay, dest_adr, tmp[wcnt]); |
end |
|
n = n + bsize +1; |
end |
|
// read sdrams |
my_dat = 0; |
for (n=0; n < TST_RUN; n=n+1) |
begin |
my_adr = (n << 2); |
dest_adr = dest_adr0 + my_adr; |
my_dat = my_adr + my_dat + kro0 + kro1 + bas0 + bas1 + wbl0 + wbl1 + cl0 + cl1 + bl0 + bl1 + cyc_delay + stb_delay; |
|
wbm.wb_cmp(cyc_delay, stb_delay, dest_adr, my_dat +2); |
end |
end |
end |
end |
end |
|
// show Wishbone-Master-model current-error-counter |
wbm.show_cur_err_cnt; |
$display("\nSDRAM/SRAM block copy test-2- ended"); |
|
end |
endtask // tst_blk_cpy2 |
|
/verilog/wb_master_model.v
0,0 → 1,408
/////////////////////////////////////////////////////////////////////// |
//// //// |
//// WISHBONE rev.B2 Wishbone Master model //// |
//// //// |
//// //// |
//// Author: Richard Herveille //// |
//// richard@asics.ws //// |
//// www.asics.ws //// |
//// //// |
//// Downloaded from: http://www.opencores.org/projects/mem_ctrl //// |
//// //// |
/////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2001 Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
/////////////////////////////////////////////////////////////////////// |
|
// CVS Log |
// |
// $Id: wb_master_model.v,v 1.1 2002-03-06 15:10:34 rherveille Exp $ |
// |
// $Date: 2002-03-06 15:10:34 $ |
// $Revision: 1.1 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// |
`include "timescale.v" |
|
module wb_master_model(clk, rst, adr, din, dout, cyc, stb, we, sel, ack, err, rty); |
|
// |
// parameters |
// |
parameter dwidth = 32; |
parameter awidth = 32; |
|
// |
// inputs & outputs |
// |
input clk, rst; |
output [awidth -1:0] adr; |
input [dwidth -1:0] din; |
output [dwidth -1:0] dout; |
output cyc, stb; |
output we; |
output [dwidth/8 -1:0] sel; |
input ack, err, rty; |
|
// |
// variables |
// |
reg [awidth -1:0] adr; |
reg [dwidth -1:0] dout; |
reg cyc, stb; |
reg we; |
reg [dwidth/8 -1:0] sel; |
|
reg [dwidth -1:0] q; |
|
integer err_cur_cnt, err_tot_cnt, err_wb_cnt, err_watchdog; |
|
|
// |
// module body |
// |
|
// check ack, err and rty assertion |
always@(ack or err or rty) |
begin |
case ({ack, err, rty}) |
// ok-states |
// 3'b000: // none asserted |
// 3'b001: // only rty asserted |
// 3'b010: // only err asserted |
// 3'b100: // only ack asserted |
|
// fault-states |
3'b011: // oops, err and rty |
begin |
err_wb_cnt = err_wb_cnt +1; |
$display("Wishbone error: ERR_I and RTY_I are both asserted at time %t.", $time); |
end |
3'b101: // oops, ack and rty |
begin |
err_wb_cnt = err_wb_cnt +1; |
$display("Wishbone error: ACK_I and RTY_I are both asserted at time %t.", $time); |
end |
3'b110: // oops, ack and err |
begin |
err_wb_cnt = err_wb_cnt +1; |
$display("Wishbone error: ACK_I and ERR_I are both asserted at time %t.", $time); |
end |
3'b111: // oops, ack, err and rty |
begin |
err_wb_cnt = err_wb_cnt +1; |
$display("Wishbone error: ACK_I, ERR_I and RTY_I are all asserted at time %t.", $time); |
end |
endcase |
|
if (err_wb_cnt > err_watchdog) |
begin |
$display("\nTestbench stopped. More than %d wishbone errors detected.\n", err_watchdog); |
$stop; |
end |
end |
|
// initial settings |
initial |
begin |
//adr = 32'hxxxx_xxxx; |
//adr = 0; |
adr = {awidth{1'bx}}; |
dout = {dwidth{1'bx}}; |
cyc = 1'b0; |
stb = 1'bx; |
we = 1'hx; |
sel = {dwidth/8{1'bx}}; |
|
err_tot_cnt = 0; |
err_cur_cnt = 0; |
err_wb_cnt = 0; |
err_watchdog = 10; |
|
#1; |
$display("\nINFO: WISHBONE MASTER MODEL INSTANTIATED (%m)\n"); |
end |
|
|
//////////////////////////// |
// |
// Wishbone write cycle |
// |
|
task wb_write; |
input delay; |
integer delay; |
input stb_delay; |
integer stb_delay; |
|
input [awidth -1:0] a; |
input [dwidth -1:0] d; |
|
begin |
|
// wait initial delay |
repeat(delay) @(posedge clk); |
|
#1; |
// assert cyc_signal |
cyc = 1'b1; |
stb = 1'b0; |
|
// wait for stb_assertion |
repeat(stb_delay) @(posedge clk); |
|
// assert wishbone signals |
adr = a; |
dout = d; |
stb = 1'b1; |
we = 1'b1; |
sel = {dwidth/8{1'b1}}; |
@(posedge clk); |
|
// wait for acknowledge from slave |
// err is treated as normal ack |
// rty is ignored (thus retrying cycle) |
while(~ (ack || err)) @(posedge clk); |
|
// negate wishbone signals |
#1; |
cyc = 1'b0; |
stb = 1'bx; |
adr = {awidth{1'bx}}; |
dout = {dwidth{1'bx}}; |
we = 1'hx; |
sel = {dwidth/8{1'bx}}; |
|
end |
endtask |
|
task wb_write_sel; |
input delay; |
integer delay; |
input stb_delay; |
integer stb_delay; |
|
input [dwidth/8 -1:0] s; |
input [awidth -1:0] a; |
input [dwidth -1:0] d; |
|
begin |
|
// wait initial delay |
repeat(delay) @(posedge clk); |
|
#1; |
// assert cyc_signal |
cyc = 1'b1; |
stb = 1'b0; |
|
// wait for stb_assertion |
repeat(stb_delay) @(posedge clk); |
|
// assert wishbone signals |
adr = a; |
dout = d; |
stb = 1'b1; |
we = 1'b1; |
sel = s; |
@(posedge clk); |
|
// wait for acknowledge from slave |
// err is treated as normal ack |
// rty is ignored (thus retrying cycle) |
while(~ (ack || err)) @(posedge clk); |
|
// negate wishbone signals |
#1; |
cyc = 1'b0; |
stb = 1'bx; |
adr = {awidth{1'bx}}; |
dout = {dwidth{1'bx}}; |
we = 1'hx; |
sel = {dwidth/8{1'bx}}; |
|
end |
endtask |
|
//////////////////////////// |
// |
// Wishbone read cycle |
// |
|
task wb_read; |
input delay; |
integer delay; |
input stb_delay; |
integer stb_delay; |
|
input [awidth -1:0] a; |
output [dwidth -1:0] d; |
|
begin |
|
// wait initial delay |
repeat(delay) @(posedge clk); |
|
#1; |
// assert cyc_signal |
cyc = 1'b1; |
stb = 1'b0; |
|
// wait for stb_assertion |
repeat(stb_delay) @(posedge clk); |
|
// assert wishbone signals |
adr = a; |
dout = {dwidth{1'bx}}; |
stb = 1'b1; |
we = 1'b0; |
sel = {dwidth/8{1'b1}}; |
@(posedge clk); |
|
// wait for acknowledge from slave |
// err is treated as normal ack |
// rty is ignored (thus retrying cycle) |
while(~ (ack || err)) @(posedge clk); |
|
// negate wishbone signals |
#1; |
cyc = 1'b0; |
stb = 1'bx; |
adr = {awidth{1'bx}}; |
dout = {dwidth{1'bx}}; |
we = 1'hx; |
sel = {dwidth/8{1'bx}}; |
d = din; |
|
end |
endtask |
|
task wb_read_sel; |
input delay; |
integer delay; |
input stb_delay; |
integer stb_delay; |
|
input [dwidth/8 -1:0] s; |
input [awidth -1:0] a; |
output [dwidth -1:0] d; |
|
begin |
|
// wait initial delay |
repeat(delay) @(posedge clk); |
|
#1; |
// assert cyc_signal |
cyc = 1'b1; |
stb = 1'b0; |
|
// wait for stb_assertion |
repeat(stb_delay) @(posedge clk); |
|
// assert wishbone signals |
adr = a; |
dout = {dwidth{1'bx}}; |
stb = 1'b1; |
we = 1'b0; |
sel = s; |
@(posedge clk); |
|
// wait for acknowledge from slave |
// err is treated as normal ack |
// rty is ignored (thus retrying cycle) |
while(~ (ack || err)) @(posedge clk); |
|
// negate wishbone signals |
#1; |
cyc = 1'b0; |
stb = 1'bx; |
adr = {awidth{1'bx}}; |
dout = {dwidth{1'bx}}; |
we = 1'hx; |
sel = {dwidth/8{1'bx}}; |
d = din; |
|
end |
endtask |
|
//////////////////////////// |
// |
// Wishbone compare cycle |
// read data from location and compare with expected data |
// |
|
task wb_cmp; |
input delay; |
integer delay; |
input stb_delay; |
integer stb_delay; |
|
input [awidth -1:0] a; |
input [dwidth -1:0] d_exp; |
|
begin |
wb_read (delay, stb_delay, a, q); |
|
if (d_exp !== q) |
begin |
err_tot_cnt = err_tot_cnt +1; |
err_cur_cnt = err_cur_cnt +1; |
$display("Data compare error(%d) at time %t. Received %h, expected %h at address %h", err_tot_cnt, $time, q, d_exp, a); |
end |
|
if (err_tot_cnt > err_watchdog) |
begin |
$display("\nTestbench stopped. More than %d errors detected.\n", err_watchdog); |
$stop; |
end |
end |
endtask |
|
|
//////////////////////////// |
// |
// Error counter handlers |
// |
task set_cur_err_cnt; |
input value; |
begin |
err_cur_cnt = value; |
end |
endtask |
|
task show_cur_err_cnt; |
$display("\nCurrent errors detected: %d\n", err_cur_cnt); |
endtask |
|
task show_tot_err_cnt; |
$display("\nTotal errors detected: %d\n", err_tot_cnt); |
endtask |
|
endmodule |
|
/verilog/timescale.v
0,0 → 1,2
`timescale 1ns / 10ps |
|
/verilog/checkers.v
0,0 → 1,226
///////////////////////////////////////////////////////////////////// |
//// //// |
//// OpenCores Memory Controller Testbench //// |
//// Additional checks //// |
//// //// |
//// Author: Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// //// |
//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2001, 2002 Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
// CVS Log |
// |
// $Id: checkers.v,v 1.1 2002-03-06 15:10:34 rherveille Exp $ |
// |
// $Date: 2002-03-06 15:10:34 $ |
// $Revision: 1.1 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
|
`include "timescale.v" |
|
////////////////////////////// |
// external bus-master model |
// |
|
module bm_model(br, bg, chk); |
|
// parameters |
reg on_off; |
|
// inputs |
output br; |
reg br; |
input bg; |
input chk; |
|
integer delay; |
|
initial |
begin |
on_off = 0; |
br = 1'b0; |
end |
|
always |
begin |
wait(on_off) |
|
delay = ($random >> 24) +10; |
|
// wait a random moment |
# delay; |
|
// assert bus_request |
br = 1'b1; |
$display("External bus-master requesting bus at time %t... ", $time); |
|
// wait for assertion of bus_grant |
wait(bg); |
$display("Bus granted at time %t.", $time); |
|
// check the memory controller output_enable signal, should be negated |
if (chk) |
$display("Memory controller output signals not in tri-state."); |
|
delay = ($random >> 24) +10; |
|
// wait a random moment |
# delay; |
|
// negate bus_request |
br = 1'b0; |
$display("External bus-master releasing bus at time %t ...", $time); |
|
// wait for negation of bus_grant |
wait(!bg); |
$display("Bus released at time %t.", $time); |
|
end |
endmodule |
|
|
// |
// WISHBONE Bus Watchdog |
// |
module watch_dog(clk, cyc_i, ack_i, adr_i); |
|
// parameters |
parameter count = 1000; |
|
// inputs |
input clk; |
input cyc_i; |
input ack_i; |
input [31:0] adr_i; |
|
// variables |
integer cnt; |
|
// module body |
always@(posedge clk) |
if (!cyc_i || ack_i) |
cnt <= #1 count; |
else |
begin |
cnt <= #1 cnt -1; |
|
if (cnt == 0) |
begin |
$display("\n\n WATCHDOG TIMER EXPIRED \n\n"); |
$display("Time: %t, address: %h", $time, adr_i); |
$stop; |
end |
end |
endmodule |
|
|
// |
// Check status of Wishbone ERR_O line |
// |
|
module err_check(err, sel_par); |
|
// |
// inputs |
// |
input err; |
input sel_par; |
|
// |
// module body |
// |
always@(err) |
case (err) |
1'b1: |
if(sel_par) |
begin |
$display("*"); |
$display("* ERROR: WISHBONE ERR_O asserted at time %t", $time); |
$display("*"); |
end |
else |
$display("Wishbone ERR_O asserted (ok)"); |
|
1'bx: |
begin |
$display("*"); |
$display("* ERROR: WISHBONE ERR_O undefined at time %t", $time); |
$display("*"); |
end |
endcase |
endmodule |
|
// |
// Check status of Wishbone ERR_O line |
// |
|
module cs_check(cs); |
|
// |
// inputs |
// |
input [7:0] cs; |
|
// |
// module body |
// |
always@(cs) |
begin |
if ((cs[7] == 1'bx) | (cs[6] == 1'bx) | (cs[5] == 1'bx) | (cs[4] == 1'bx) | |
(cs[3] == 1'bx) | (cs[2] == 1'bx) | (cs[1] == 1'bx) | (cs[0] == 1'bx) ) |
begin |
$display("*"); |
$display("* ERROR: CHIP SELECT SIGNAL UNDEFINED at time %t", $time); |
$display("*"); |
end |
|
if ((!cs[7] & !(&cs[6:0]) ) | |
(!cs[6] & !(&{cs[7] , cs[5:0]}) ) | |
(!cs[5] & !(&{cs[7:6], cs[4:0]}) ) | |
(!cs[4] & !(&{cs[7:5], cs[3:0]}) ) | |
(!cs[3] & !(&{cs[7:4], cs[2:0]}) ) | |
(!cs[2] & !(&{cs[7:3], cs[1:0]}) ) | |
(!cs[1] & !(&{cs[7:2], cs[0]} ) ) | |
(!cs[0] & !(&cs[7:1]) ) ) |
begin |
$display("*"); |
$display("* ERROR: MULTIPLE CHIP SELECT SIGNALS ASSERTED at time %t", $time); |
$display("*"); |
end |
end |
|
endmodule |
|