modelsim仿真sdram,如何修改仿真模型参数?
本帖最后由 german010 于 2013-2-22 07:13 编辑请教大家个问题:
我用 mt48lc8m16a2的仿真模型代替HY57V641620ETP-H来进行仿真,工作频率为100Mhz,
出现如下ERROR提示,应该是时序违例造成的吧,应该是模型代码最下面的参数 不满足100Mhz工作时的时序要求,应该如何修改?
run 2ms
#Note : Cyclone IV E PLL was reset
# Time: 0 nsInstance: modelsim_test_tb.sdr_test.uut_sysctrl.uut_PLL_ctrl.altpll_component.cycloneiii_pll.pll3
# ** Error: E:/log/13.02.18/232SDRAM3_1_many/mt48lc8m16a2.v(892): $hold( posedge Clk:260 ns, Cke:260 ns, 800 ps );
# Time: 260 nsIteration: 6Instance: /modelsim_test_tb/mt48lc8m16a2
# ** Error: E:/log/13.02.18/232SDRAM3_1_many/mt48lc8m16a2.v(893): $hold( posedge Clk:260 ns, Cs_n:260 ns, 800 ps );
# Time: 260 nsIteration: 6Instance: /modelsim_test_tb/mt48lc8m16a2
#Note : Cyclone IV E PLL locked to incoming clock
# Time: 420 nsInstance: modelsim_test_tb.sdr_test.uut_sysctrl.uut_PLL_ctrl.altpll_component.cycloneiii_pll.pll3
# ** Error: E:/log/13.02.18/232SDRAM3_1_many/mt48lc8m16a2.v(889): $width( negedge Clk:420 ns, :422187 ps, 2500 ps );
# Time: 422187 psIteration: 3Instance: /modelsim_test_tb/mt48lc8m16a2
# ** Error: E:/log/13.02.18/232SDRAM3_1_many/mt48lc8m16a2.v(890): $period( negedge Clk:420 ns, :427187 ps, 7500 ps );
# Time: 427187 psIteration: 3Instance: /modelsim_test_tb/mt48lc8m16a2
下面是 mt48lc8m16a2的仿真模型,大家帮忙看看
/****************************************************************************************
*
* File Name:MT48LC8M16A2.V
* Version:0.0f
* Date:July 8th, 1999
* Model:BUS Functional
* Simulator:Model Technology (PC version 5.2e PE)
*
* Dependencies:None
*
* Author:Son P. Huynh
* Email:sphuynh@micron.com
* Phone:(208) 368-3825
* Company:Micron Technology, Inc.
* Model:MT48LC8M16A2 (2Meg x 16 x 4 Banks)
*
*Description:Micron 128Mb SDRAM Verilog model
*
* Limitation:- Doesn't check for 4096 cycle refresh
*
* Note:- Set simulator resolution to "ps" accuracy
* - 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.
*
* Copyright © 1998 Micron Semiconductor Products, Inc.
* All rights researved
*
* Rev Author Phone Date Changes
* ---------------------------------------------------------------------------------
* 0.0fSon Huynh 208-368-382507/08/1999- Fix tWR = 1 Clk + 7.5 ns (Auto)
* Micron Technology Inc. - Fix tWR = 15 ns (Manual)
* - Fix tRP (Autoprecharge to AutoRefresh)
*
* 0.0aSon Huynh 208-368-382505/13/1998- First Release (from 64Mb rev 0.0e)
* Micron Technology Inc.
****************************************************************************************/
`timescale 1ns / 1ps
module mt48lc8m16a2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
parameter addr_bits = 12;
parameter data_bits = 16;
//parameter col_bits= 9;
parameter col_bits= 8;
//parameter mem_sizes = 2097151;
parameter mem_sizes = 1048575; // 2 Meg
inout Dq;
input Addr;
input Ba;
input Clk;
input Cke;
input Cs_n;
input Ras_n;
input Cas_n;
input We_n;
input Dqm;
reg Bank0 ;
reg Bank1 ;
reg Bank2 ;
reg Bank3 ;
reg Bank_addr ; // Bank Address Pipeline
reg Col_addr ; // Column Address Pipeline
reg Command ; // Command Operation Pipeline
reg Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline
reg B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr;
reg Mode_reg;
reg Dq_reg, Dq_dqm;
reg 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 Bank_precharge ; // Precharge Command
reg A10_precharge ; // Addr = 1 (All banks)
reg Auto_precharge ; // RW AutoPrecharge (Bank)
reg Read_precharge ; // RAutoPrecharge
reg Write_precharge ; //W AutoPrecharge
integer Count_precharge ; // RW AutoPrecharge (Counter)
reg RW_interrupt_read; // RW Interrupt Read with Auto Precharge
reg RW_interrupt_write ; // RW Interrupt Write with Auto Precharge
reg Data_in_enable;
reg Data_out_enable;
reg Bank, Previous_bank;
reg Row;
reg Col, Col_brst;
// Internal system clock
reg CkeZ, Sys_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 & ~Mode_reg & ~Mode_reg;
wire Burst_length_2 = ~Mode_reg & ~Mode_reg &Mode_reg;
wire Burst_length_4 = ~Mode_reg &Mode_reg & ~Mode_reg;
wire Burst_length_8 = ~Mode_reg &Mode_reg &Mode_reg;
// CAS Latency Decode
wire Cas_latency_2 = ~Mode_reg &Mode_reg & ~Mode_reg;
wire Cas_latency_3 = ~Mode_reg &Mode_reg &Mode_reg;
// Write Burst Mode
wire Write_burst_mode = Mode_reg;
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 -75 (PC133) and CAS Latency = 2
parameter tAC= 6.0;
parameter tHZ= 7.0;
parameter tOH= 2.7;
parameter tMRD = 2.0; // 2 Clk Cycles
parameter tRAS =44.0;
parameter tRC=66.0;
parameter tRCD =20.0;
parameter tRP=20.0;
parameter tRRD =15.0;
parameter tWRa = 7.5; // A2 Version - Auto precharge mode only (1 Clk + 7.5 ns)
parameter tWRp =0.0; // A2 Version - Precharge mode only (15 ns)
// Timing Check variable
integer MRD_chk;
integer WR_counter ;
time WR_chk ;
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_chk, WR_chk, WR_chk, WR_chk} = 0;
{WR_counter, WR_counter, WR_counter, WR_counter} = 0;
{RW_interrupt_read, RW_interrupt_read, RW_interrupt_read, RW_interrupt_read} = 0;
{RW_interrupt_write, RW_interrupt_write, RW_interrupt_write, RW_interrupt_write} = 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, 0, " ns", 12);
//$readmemh("bank0.txt", Bank0);
//$readmemh("bank1.txt", Bank1);
//$readmemh("bank2.txt", Bank2);
//$readmemh("bank3.txt", Bank3);
end
// System clock generator
always begin
@ (posedge Clk) begin
Sys_clk = CkeZ;
CkeZ = Cke;
end
@ (negedge Clk) begin
Sys_clk = 1'b0;
end
end
always @ (posedge Sys_clk) begin
// Internal Commamd Pipelined
Command = Command;
Command = Command;
Command = Command;
Command = `NOP;
Col_addr = Col_addr;
Col_addr = Col_addr;
Col_addr = Col_addr;
Col_addr = {col_bits{1'b0}};
Bank_addr = Bank_addr;
Bank_addr = Bank_addr;
Bank_addr = Bank_addr;
Bank_addr = 2'b0;
Bank_precharge = Bank_precharge;
Bank_precharge = Bank_precharge;
Bank_precharge = Bank_precharge;
Bank_precharge = 2'b0;
A10_precharge = A10_precharge;
A10_precharge = A10_precharge;
A10_precharge = A10_precharge;
A10_precharge = 1'b0;
// Dqm pipeline for Read
Dqm_reg0 = Dqm_reg1;
Dqm_reg1 = Dqm;
// Read or Write with Auto Precharge Counter
if (Auto_precharge == 1'b1) begin
Count_precharge = Count_precharge + 1;
end
if (Auto_precharge == 1'b1) begin
Count_precharge = Count_precharge + 1;
end
if (Auto_precharge == 1'b1) begin
Count_precharge = Count_precharge + 1;
end
if (Auto_precharge == 1'b1) begin
Count_precharge = Count_precharge + 1;
end
// tMRD Counter
MRD_chk = MRD_chk + 1;
// tWR Counter for Write
WR_counter = WR_counter + 1;
WR_counter = WR_counter + 1;
WR_counter = WR_counter + 1;
WR_counter = WR_counter + 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 == 3'b010)
$display (" CAS Latency = 2");
else if (Addr == 3'b011)
$display (" CAS Latency = 3");
else
$display (" CAS Latency = Reserved");
// Burst Length
if (Addr == 3'b000)
$display (" Burst Length = 1");
else if (Addr == 3'b001)
$display (" Burst Length = 2");
else if (Addr == 3'b010)
$display (" Burst Length = 4");
else if (Addr == 3'b011)
$display (" Burst Length = 8");
else if (Addr == 4'b0111)
$display (" Burst Length = Full");
else
$display (" Burst Length = Reserved");
// Burst Type
if (Addr == 1'b0)
$display (" Burst Type = Sequential");
else if (Addr == 1'b1)
$display (" Burst Type = Interleaved");
else
$display (" Burst Type = Reserved");
// Write Burst Mode
if (Addr == 1'b0)
$display (" Write Burst Mode = Programmed Burst Length");
else if (Addr == 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 ;
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 ("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 ;
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 ;
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 ;
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 not Precharged.", $time);
end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin
$display ("at time %t ERROR: Bank 1 is not Precharged.", $time);
end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin
$display ("at time %t ERROR: Bank 2 is not Precharged.", $time);
end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: Bank 3 is 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 == 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 bank", $time);
end
// tWR violation check for write
if (($time - WR_chk < tWRp) || ($time - WR_chk < tWRp) ||
($time - WR_chk < tWRp) || ($time - WR_chk < tWRp)) begin
$display ("at time %t ERROR: tWR violation during Precharge all bank", $time);
end
end else if (Addr == 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_chk < 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 == 1'b1)) begin
Data_in_enable = 1'b0;
end
// Precharge Command Pipeline for Read
if (Cas_latency_3 == 1'b1) begin
Command = `PRECH;
Bank_precharge = Ba;
A10_precharge = Addr;
end else if (Cas_latency_2 == 1'b1) begin
Command = `PRECH;
Bank_precharge = Ba;
A10_precharge = Addr;
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 = `BST;
end else if (Cas_latency_2 == 1'b1) begin
Command = `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 == 1'b1) begin
Command = `READ_A;
end else begin
Command = `READ;
end
Col_addr = Addr;
Bank_addr = Ba;
end else if (Cas_latency_2 == 1'b1) begin
if (Addr == 1'b1) begin
Command = `READ_A;
end else begin
Command = `READ;
end
Col_addr = Addr;
Bank_addr = Ba;
end
// Read interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Write Command
end else if (Write_enable == 1'b1) begin
if (Addr == 1'b1) begin
Command = `WRITE_A;
end else begin
Command = `WRITE;
end
Col_addr = Addr;
Bank_addr = Ba;
// Write interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Write interrupt Read (terminate Read immediately)
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
// Interrupting a Write with Autoprecharge
if (Auto_precharge == 1'b1 && Write_precharge == 1'b1) begin
RW_interrupt_write = 1'b1;
if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, Bank);
end
// Interrupting a Read with Autoprecharge
if (Auto_precharge == 1'b1 && Read_precharge == 1'b1) begin
RW_interrupt_read = 1'b1;
if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, Bank);
end
// Read or Write with Auto Precharge
if (Addr == 1'b1) begin
Auto_precharge = 1'b1;
Count_precharge = 0;
if (Read_enable == 1'b1) begin
Read_precharge = 1'b1;
end else if (Write_enable == 1'b1) begin
Write_precharge = 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 == 1'b1) && (Read_precharge == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
((Burst_length_1 == 1'b1 && Count_precharge >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge >= 8))) ||
(RW_interrupt_read == 1'b1)) begin // Case 3
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Auto_precharge = 1'b0;
Read_precharge = 1'b0;
RW_interrupt_read = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge == 1'b1) && (Read_precharge == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge >= 8))) ||
(RW_interrupt_read == 1'b1)) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Auto_precharge = 1'b0;
Read_precharge = 1'b0;
RW_interrupt_read = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge == 1'b1) && (Read_precharge == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge >= 8))) ||
(RW_interrupt_read == 1'b1)) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Auto_precharge = 1'b0;
Read_precharge = 1'b0;
RW_interrupt_read = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge == 1'b1) && (Read_precharge == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge >= 8))) ||
(RW_interrupt_read == 1'b1)) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Auto_precharge = 1'b0;
Read_precharge = 1'b0;
RW_interrupt_read = 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 == `PRECH) begin // Precharge terminate a read with same bank or all banks
if (Bank_precharge == Bank || A10_precharge == 1'b1) begin
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
end else if (Command == `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 == `READ || Command == `READ_A) begin
Bank = Bank_addr;
Col = Col_addr;
Col_brst = Col_addr;
if (Bank_addr == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr == 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 == `WRITE || Command == `WRITE_A) begin
Bank = Bank_addr;
Col = Col_addr;
Col_brst = Col_addr;
if (Bank_addr == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr == 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 = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm == 1'b0) Dq_dqm [ 7 : 0] = Dq [ 7 : 0];
if (Dqm == 1'b0) Dq_dqm = Dq ;
// Write to memory
if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq_dqm ;
if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq_dqm ;
if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq_dqm ;
if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq_dqm ;
// 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_chk = $time;
WR_counter = 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 = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm_reg0 == 1'b1) Dq_dqm [ 7 : 0] = 8'bz;
if (Dqm_reg0 == 1'b1) Dq_dqm = 8'bz;
// Display result
Dq_reg = #tAC Dq_dqm ;
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 @ (WR_counter) begin
if ((Auto_precharge == 1'b1) && (Write_precharge == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge >= 8))) ||
(RW_interrupt_write == 1'b1 && WR_counter >= 2)) begin // Case 3 (stop count when interrupt)
Auto_precharge = 1'b0;
Write_precharge = 1'b0;
RW_interrupt_write = 1'b0;
#tWRa; // Wait for tWR
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
end
always @ (WR_counter) begin
if ((Auto_precharge == 1'b1) && (Write_precharge == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge >= 8))) ||
(RW_interrupt_write == 1'b1 && WR_counter >= 2)) begin
Auto_precharge = 1'b0;
Write_precharge = 1'b0;
RW_interrupt_write = 1'b0;
#tWRa; // Wait for tWR
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
end
always @ (WR_counter) begin
if ((Auto_precharge == 1'b1) && (Write_precharge == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge >= 8))) ||
(RW_interrupt_write == 1'b1 && WR_counter >= 2)) begin
Auto_precharge = 1'b0;
Write_precharge = 1'b0;
RW_interrupt_write = 1'b0;
#tWRa; // Wait for tWR
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
end
always @ (WR_counter) begin
if ((Auto_precharge == 1'b1) && (Write_precharge == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge >= 8))) ||
(RW_interrupt_write == 1'b1 && WR_counter >= 2)) begin
Auto_precharge = 1'b0;
Write_precharge = 1'b0;
RW_interrupt_write = 1'b0;
#tWRa; // Wait for tWR
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 == 1'b0) begin // Sequential Burst
Col_temp = Col + 1;
end else if (Mode_reg == 1'b1) begin // Interleaved Burst
Col_temp =Burst_counter ^Col_brst;
Col_temp =Burst_counter ^Col_brst;
Col_temp =Burst_counter ^Col_brst;
end
// Burst Length
if (Burst_length_2) begin // Burst Length = 2
Col = Col_temp ;
end else if (Burst_length_4) begin // Burst Length = 4
Col = Col_temp ;
end else if (Burst_length_8) begin // Burst Length = 8
Col = Col_temp ;
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 -75 (PC133) 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= 10.0, // Clock Cycle Time100mhz
tCK= 7.5, // Clock Cycle Time133mhz
tDH=0.8, // Data-in Hold Time
tDS=1.5, // Data-in Setup Time
tCKH =0.8, // CKE HoldTime
tCKS =1.5, // CKE Setup Time
tCMH =0.8, // CS#, RAS#, CAS#, WE#, DQM# HoldTime
tCMS =1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time
Ln#
888 $width (posedge Clk, tCH);
889 $width (negedge Clk, tCL);
890 $period (negedge Clk, tCK);
891 $period (posedge Clk, tCK);
892 $setuphold(posedge Clk, Cke, tCKS, tCKH);
893 $setuphold(posedge Clk, Cs_n,tCMS, tCMH);
894 $setuphold(posedge Clk, Cas_n, tCMS, tCMH);
895 $setuphold(posedge Clk, Ras_n, tCMS, tCMH);
896 $setuphold(posedge Clk, We_n,tCMS, tCMH);
897 $setuphold(posedge Clk, Addr,tAS,tAH);
898 $setuphold(posedge Clk, Ba, tAS,tAH);
899 $setuphold(posedge Clk, Dqm, tCMS, tCMH);
900 $setuphold(posedge Dq_chk, Dq, tDS,tDH);
endspecify
endmodule
页:
[1]