OpenCores
URL https://opencores.org/ocsvn/m1_core/m1_core/trunk

Subversion Repositories m1_core

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 35 to Rev 36
    Reverse comparison

Rev 35 → Rev 36

/trunk/hdl/behav/xilinx_unisim/BUFG.v
0,0 → 1,33
// $Header: /home/marcus/revision_ctrl_test/oc_cvs/cvs/m1_core/hdl/behav/xilinx_unisim/BUFG.v,v 1.1 2008-11-07 13:12:06 fafa1971 Exp $
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 1995/2004 Xilinx, Inc.
// All Right Reserved.
///////////////////////////////////////////////////////////////////////////////
// ____ ____
// / /\/ /
// /___/ \ / Vendor : Xilinx
// \ \ \/ Version : 8.1i (I.13)
// \ \ Description : Xilinx Functional Simulation Library Component
// / / Global Clock Buffer
// /___/ /\ Filename : BUFG.v
// \ \ / \ Timestamp : Thu Mar 25 16:42:14 PST 2004
// \___\/\___\
//
// Revision:
// 03/23/04 - Initial version.
// End Revision
 
`timescale 100 ps / 10 ps
 
 
module BUFG (O, I);
 
output O;
 
input I;
 
buf B1 (O, I);
 
 
endmodule
 
/trunk/hdl/behav/xilinx_unisim/DCM_SP.v
0,0 → 1,1244
// $Header: /home/marcus/revision_ctrl_test/oc_cvs/cvs/m1_core/hdl/behav/xilinx_unisim/DCM_SP.v,v 1.1 2008-11-07 13:12:06 fafa1971 Exp $
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 1995/2004 Xilinx, Inc.
// All Right Reserved.
///////////////////////////////////////////////////////////////////////////////
// ____ ____
// / /\/ /
// /___/ \ / Vendor : Xilinx
// \ \ \/ Version : 9.2i (J.36)
// \ \ Description : Xilinx Function Simulation Library Component
// / / Digital Clock Manager
// /___/ /\ Filename : DCM_SP.v
// \ \ / \ Timestamp :
// \___\/\___\
//
// Revision:
// 02/28/06 - Initial version.
// 05/09/06 - Add clkin_ps_mkup and clkin_ps_mkup_win for phase shifting (CR 229789).
// 06/14/06 - Add clkin_ps_mkup_flag for multiple cycle delays (CR233283).
// 07/21/06 - Change range of variable phase shifting to +/- integer of 20*(Period-3ns).
// Give warning not support initial phase shifting for variable phase shifting.
// (CR 235216).
// 09/22/06 - Add lock_period and lock_fb to clkfb_div block (CR 418722).
// 12/19/06 - Add clkfb_div_en for clkfb2x divider (CR431210).
// 04/06/07 - Enable the clock out in clock low time after reset in model
// clock_divide_by_2 (CR 437471).
// End Revision
 
 
`timescale 1 ps / 1 ps
 
module DCM_SP (
CLK0, CLK180, CLK270, CLK2X, CLK2X180, CLK90,
CLKDV, CLKFX, CLKFX180, LOCKED, PSDONE, STATUS,
CLKFB, CLKIN, DSSEN, PSCLK, PSEN, PSINCDEC, RST);
 
parameter CLKDV_DIVIDE = 2.0;
parameter integer CLKFX_DIVIDE = 1;
parameter integer CLKFX_MULTIPLY = 4;
parameter CLKIN_DIVIDE_BY_2 = "FALSE";
parameter CLKIN_PERIOD = 10.0; // non-simulatable
parameter CLKOUT_PHASE_SHIFT = "NONE";
parameter CLK_FEEDBACK = "1X";
parameter DESKEW_ADJUST = "SYSTEM_SYNCHRONOUS"; // non-simulatable
parameter DFS_FREQUENCY_MODE = "LOW";
parameter DLL_FREQUENCY_MODE = "LOW";
parameter DSS_MODE = "NONE"; // non-simulatable
parameter DUTY_CYCLE_CORRECTION = "TRUE";
parameter FACTORY_JF = 16'hC080; // non-simulatable
parameter integer MAXPERCLKIN = 1000000; // non-modifiable simulation parameter
parameter integer MAXPERPSCLK = 100000000; // non-modifiable simulation parameter
parameter integer PHASE_SHIFT = 0;
parameter integer SIM_CLKIN_CYCLE_JITTER = 300; // non-modifiable simulation parameter
parameter integer SIM_CLKIN_PERIOD_JITTER = 1000; // non-modifiable simulation parameter
parameter STARTUP_WAIT = "FALSE"; // non-simulatable
 
 
localparam PS_STEP = 25;
 
input CLKFB, CLKIN, DSSEN;
input PSCLK, PSEN, PSINCDEC, RST;
 
output CLK0, CLK180, CLK270, CLK2X, CLK2X180, CLK90;
output CLKDV, CLKFX, CLKFX180, LOCKED, PSDONE;
output [7:0] STATUS;
 
reg CLK0, CLK180, CLK270, CLK2X, CLK2X180, CLK90;
reg CLKDV, CLKFX, CLKFX180;
 
wire locked_out_out;
wire clkfb_in, clkin_in, dssen_in;
wire psclk_in, psen_in, psincdec_in, rst_in;
reg clk0_out;
reg clk2x_out, clkdv_out;
reg clkfx_out, clkfx180_en;
reg rst_flag;
reg locked_out, psdone_out, ps_overflow_out, ps_lock;
reg clkfb_div, clkfb_chk, clkfb_div_en;
integer clkdv_cnt;
 
reg [1:0] clkfb_type;
reg [8:0] divide_type;
reg clkin_type;
reg [1:0] ps_type;
reg [3:0] deskew_adjust_mode;
reg dfs_mode_type;
reg dll_mode_type;
reg clk1x_type;
integer ps_in;
 
reg lock_period, lock_delay, lock_clkin, lock_clkfb;
reg first_time_locked;
reg en_status;
reg ps_overflow_out_ext;
reg clkin_lost_out_ext;
reg clkfx_lost_out_ext;
reg [1:0] lock_out;
reg lock_out1_neg;
reg lock_fb, lock_ps, lock_ps_dly, lock_fb_dly, lock_fb_dly_tmp;
reg fb_delay_found;
reg clock_stopped;
reg clkin_chkin, clkfb_chkin;
 
wire chk_enable, chk_rst;
wire clkin_div;
wire lock_period_pulse;
wire lock_period_dly, lock_period_dly1;
 
reg clkin_ps, clkin_ps_tmp, clkin_ps_mkup, clkin_ps_mkup_win, clkin_ps_mkup_flag;
reg clkin_fb;
 
time FINE_SHIFT_RANGE;
//time ps_delay, ps_delay_init, ps_delay_md, ps_delay_all, ps_max_range;
integer ps_delay, ps_delay_init, ps_delay_md, ps_delay_all, ps_max_range;
integer ps_delay_last;
integer ps_acc;
time clkin_edge;
time clkin_div_edge;
time clkin_ps_edge;
time delay_edge;
time clkin_period [2:0];
time period;
integer period_int, period_int2, period_int3, period_ps_tmp;
time period_div;
integer period_orig_int;
time period_orig;
time period_ps;
time clkout_delay;
time fb_delay;
time period_fx, remain_fx;
time period_dv_high, period_dv_low;
time cycle_jitter, period_jitter;
 
reg clkin_window, clkfb_window;
reg [2:0] rst_reg;
reg [12:0] numerator, denominator, gcd;
reg [23:0] i, n, d, p;
 
reg notifier;
 
initial begin
#1;
if ($realtime == 0) begin
$display ("Simulator Resolution Error : Simulator resolution is set to a value greater than 1 ps.");
$display ("In order to simulate the DCM_SP, the simulator resolution must be set to 1ps or smaller.");
$finish;
end
end
 
initial begin
case (2.0)
1.5 : divide_type = 'd3;
2.0 : divide_type = 'd4;
2.5 : divide_type = 'd5;
3.0 : divide_type = 'd6;
3.5 : divide_type = 'd7;
4.0 : divide_type = 'd8;
4.5 : divide_type = 'd9;
5.0 : divide_type = 'd10;
5.5 : divide_type = 'd11;
6.0 : divide_type = 'd12;
6.5 : divide_type = 'd13;
7.0 : divide_type = 'd14;
7.5 : divide_type = 'd15;
8.0 : divide_type = 'd16;
9.0 : divide_type = 'd18;
10.0 : divide_type = 'd20;
11.0 : divide_type = 'd22;
12.0 : divide_type = 'd24;
13.0 : divide_type = 'd26;
14.0 : divide_type = 'd28;
15.0 : divide_type = 'd30;
16.0 : divide_type = 'd32;
default : begin
$display("Attribute Syntax Error : The attribute CLKDV_DIVIDE on DCM_SP instance %m is set to %0.1f. Legal values for this attribute are 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, or 16.0.", CLKDV_DIVIDE);
$finish;
end
endcase
 
if ((CLKFX_DIVIDE <= 0) || (32 < CLKFX_DIVIDE)) begin
$display("Attribute Syntax Error : The attribute CLKFX_DIVIDE on DCM_SP instance %m is set to %d. Legal values for this attribute are 1 ... 32.", CLKFX_DIVIDE);
$finish;
end
 
if ((CLKFX_MULTIPLY <= 1) || (32 < CLKFX_MULTIPLY)) begin
$display("Attribute Syntax Error : The attribute CLKFX_MULTIPLY on DCM_SP instance %m is set to %d. Legal values for this attribute are 2 ... 32.", CLKFX_MULTIPLY);
$finish;
end
 
case (CLKIN_DIVIDE_BY_2)
"false" : clkin_type = 0;
"FALSE" : clkin_type = 0;
"true" : clkin_type = 1;
"TRUE" : clkin_type = 1;
default : begin
$display("Attribute Syntax Error : The attribute CLKIN_DIVIDE_BY_2 on DCM_SP instance %m is set to %s. Legal values for this attribute are TRUE or FALSE.", CLKIN_DIVIDE_BY_2);
$finish;
end
endcase
 
case (CLKOUT_PHASE_SHIFT)
"NONE" : begin
ps_in = 256;
ps_type = 0;
end
"none" : begin
ps_in = 256;
ps_type = 0;
end
"FIXED" : begin
ps_in = PHASE_SHIFT + 256;
ps_type = 1;
end
"fixed" : begin
ps_in = PHASE_SHIFT + 256;
ps_type = 1;
end
"VARIABLE" : begin
ps_in = PHASE_SHIFT + 256;
ps_type = 2;
end
"variable" : begin
ps_in = PHASE_SHIFT + 256;
ps_type = 2;
if (PHASE_SHIFT != 0)
$display("Attribute Syntax Warning : The attribute PHASE_SHIFT on DCM_SP instance %m is set to %d. The maximum variable phase shift range is only valid when initial phase shift PHASE_SHIFT is zero.", PHASE_SHIFT);
end
default : begin
$display("Attribute Syntax Error : The attribute CLKOUT_PHASE_SHIFT on DCM_SP instance %m is set to %s. Legal values for this attribute are NONE, FIXED or VARIABLE.", CLKOUT_PHASE_SHIFT);
$finish;
end
endcase
 
 
case (CLK_FEEDBACK)
"none" : clkfb_type = 2'b00;
"NONE" : clkfb_type = 2'b00;
"1x" : clkfb_type = 2'b01;
"1X" : clkfb_type = 2'b01;
"2x" : clkfb_type = 2'b10;
"2X" : clkfb_type = 2'b10;
default : begin
$display("Attribute Syntax Error : The attribute CLK_FEEDBACK on DCM_SP instance %m is set to %s. Legal values for this attribute are NONE, 1X or 2X.", CLK_FEEDBACK);
$finish;
end
endcase
 
case (DESKEW_ADJUST)
"source_synchronous" : deskew_adjust_mode = 8;
"SOURCE_SYNCHRONOUS" : deskew_adjust_mode = 8;
"system_synchronous" : deskew_adjust_mode = 11;
"SYSTEM_SYNCHRONOUS" : deskew_adjust_mode = 11;
"0" : deskew_adjust_mode = 0;
"1" : deskew_adjust_mode = 1;
"2" : deskew_adjust_mode = 2;
"3" : deskew_adjust_mode = 3;
"4" : deskew_adjust_mode = 4;
"5" : deskew_adjust_mode = 5;
"6" : deskew_adjust_mode = 6;
"7" : deskew_adjust_mode = 7;
"8" : deskew_adjust_mode = 8;
"9" : deskew_adjust_mode = 9;
"10" : deskew_adjust_mode = 10;
"11" : deskew_adjust_mode = 11;
"12" : deskew_adjust_mode = 12;
"13" : deskew_adjust_mode = 13;
"14" : deskew_adjust_mode = 14;
"15" : deskew_adjust_mode = 15;
default : begin
$display("Attribute Syntax Error : The attribute DESKEW_ADJUST on DCM_SP instance %m is set to %s. Legal values for this attribute are SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or 0 ... 15.", DESKEW_ADJUST);
$finish;
end
endcase
 
case (DFS_FREQUENCY_MODE)
"high" : dfs_mode_type = 1;
"HIGH" : dfs_mode_type = 1;
"low" : dfs_mode_type = 0;
"LOW" : dfs_mode_type = 0;
default : begin
$display("Attribute Syntax Error : The attribute DFS_FREQUENCY_MODE on DCM_SP instance %m is set to %s. Legal values for this attribute are HIGH or LOW.", DFS_FREQUENCY_MODE);
$finish;
end
endcase
 
period_jitter = SIM_CLKIN_PERIOD_JITTER;
cycle_jitter = SIM_CLKIN_CYCLE_JITTER;
 
case (DLL_FREQUENCY_MODE)
"high" : dll_mode_type = 1;
"HIGH" : dll_mode_type = 1;
"low" : dll_mode_type = 0;
"LOW" : dll_mode_type = 0;
default : begin
$display("Attribute Syntax Error : The attribute DLL_FREQUENCY_MODE on DCM_SP instance %m is set to %s. Legal values for this attribute are HIGH or LOW.", DLL_FREQUENCY_MODE);
$finish;
end
endcase
 
if ((dll_mode_type ==1) && (clkfb_type == 2'b10)) begin
$display("Attribute Syntax Error : The attributes DLL_FREQUENCY_MODE on DCM_SP instance %m is set to %s and CLK_FEEDBACK is set to %s. CLK_FEEDBACK 2X is not supported when DLL_FREQUENCY_MODE is HIGH.", DLL_FREQUENCY_MODE, CLK_FEEDBACK);
$finish;
end
 
case (DSS_MODE)
"none" : ;
"NONE" : ;
default : begin
$display("Attribute Syntax Error : The attribute DSS_MODE on DCM_SP instance %m is set to %s. Legal values for this attribute is NONE.", DSS_MODE);
$finish;
end
endcase
 
case (DUTY_CYCLE_CORRECTION)
"false" : clk1x_type = 0;
"FALSE" : clk1x_type = 0;
"true" : clk1x_type = 1;
"TRUE" : clk1x_type = 1;
default : begin
$display("Attribute Syntax Error : The attribute DUTY_CYCLE_CORRECTION on DCM_SP instance %m is set to %s. Legal values for this attribute are TRUE or FALSE.", DUTY_CYCLE_CORRECTION);
$finish;
end
endcase
 
if ((PHASE_SHIFT < -255) || (PHASE_SHIFT > 255)) begin
$display("Attribute Syntax Error : The attribute PHASE_SHIFT on DCM_SP instance %m is set to %d. Legal values for this attribute are -255 ... 255.", PHASE_SHIFT);
$display("Error : PHASE_SHIFT = %d is not -255 ... 255.", PHASE_SHIFT);
$finish;
end
 
case (STARTUP_WAIT)
"false" : ;
"FALSE" : ;
"true" : ;
"TRUE" : ;
default : begin
$display("Attribute Syntax Error : The attribute STARTUP_WAIT on DCM_SP instance %m is set to %s. Legal values for this attribute are TRUE or FALSE.", STARTUP_WAIT);
$finish;
end
endcase
end
 
//
// fx parameters
//
 
initial begin
gcd = 1;
for (i = 2; i <= CLKFX_MULTIPLY; i = i + 1) begin
if (((CLKFX_MULTIPLY % i) == 0) && ((CLKFX_DIVIDE % i) == 0))
gcd = i;
end
numerator = CLKFX_MULTIPLY / gcd;
denominator = CLKFX_DIVIDE / gcd;
end
 
//
// input wire delays
//
 
buf b_clkin (clkin_in, CLKIN);
buf b_clkfb (clkfb_in, CLKFB);
buf b_dssen (dssen_in, DSSEN);
buf b_psclk (psclk_in, PSCLK);
buf b_psen (psen_in, PSEN);
buf b_psincdec (psincdec_in, PSINCDEC);
buf b_rst (rst_in, RST);
buf #100 b_LOCKED (LOCKED, locked_out_out);
buf #100 b_PSDONE (PSDONE, psdone_out);
buf b_ps_overflow (STATUS[0], ps_overflow_out_ext);
buf b_clkin_lost (STATUS[1], clkin_lost_out_ext);
buf b_clkfx_lost (STATUS[2], clkfx_lost_out_ext);
 
assign STATUS[7:3] = 5'b0;
 
dcm_sp_clock_divide_by_2 i_clock_divide_by_2 (clkin_in, clkin_type, clkin_div, rst_in);
 
dcm_sp_maximum_period_check #("CLKIN", MAXPERCLKIN) i_max_clkin (clkin_in, rst_in);
dcm_sp_maximum_period_check #("PSCLK", MAXPERPSCLK) i_max_psclk (psclk_in, rst_in);
 
dcm_sp_clock_lost i_clkin_lost (clkin_in, first_time_locked, clkin_lost_out, rst_in);
dcm_sp_clock_lost i_clkfx_lost (CLKFX, first_time_locked, clkfx_lost_out, rst_in);
 
always @(rst_in or en_status or clkfx_lost_out or clkin_lost_out or ps_overflow_out)
if (rst_in == 1 || en_status == 0) begin
ps_overflow_out_ext = 0;
clkin_lost_out_ext = 0;
clkfx_lost_out_ext = 0;
end
else
begin
ps_overflow_out_ext = ps_overflow_out;
clkin_lost_out_ext = clkin_lost_out;
clkfx_lost_out_ext = clkfx_lost_out;
end
 
always @(posedge rst_in or posedge LOCKED)
if (rst_in == 1)
en_status <= 0;
else
en_status <= 1;
 
 
always @(clkin_div)
clkin_ps_tmp <= #(ps_delay_md) clkin_div;
 
always @(clkin_ps_tmp or clkin_ps_mkup or clkin_ps_mkup_win)
if (clkin_ps_mkup_win)
clkin_ps = clkin_ps_mkup;
else
clkin_ps = clkin_ps_tmp;
 
always @(ps_delay_last or period_int or ps_delay) begin
period_int2 = 2 * period_int;
period_int3 = 3 * period_int;
if ((ps_delay_last >= period_int && ps_delay < period_int) ||
(ps_delay_last >= period_int2 && ps_delay < period_int2) ||
(ps_delay_last >= period_int3 && ps_delay < period_int3))
clkin_ps_mkup_flag = 1;
else
clkin_ps_mkup_flag = 0;
end
 
always @(posedge clkin_div or negedge clkin_div) begin
if (ps_type == 2'b10) begin
if ((ps_delay_last > 0 && ps_delay <= 0 ) || clkin_ps_mkup_flag == 1) begin
if (clkin_div) begin
clkin_ps_mkup_win <= 1;
clkin_ps_mkup <= 1;
#1;
@(negedge clkin_div) begin
clkin_ps_mkup_win <= 1;
clkin_ps_mkup <= 0;
end
end
else begin
clkin_ps_mkup_win <= 0;
clkin_ps_mkup <= 0;
#1;
@(posedge clkin_div) begin
clkin_ps_mkup_win <= 1;
clkin_ps_mkup <= 1;
end
@(negedge clkin_div) begin
clkin_ps_mkup_win <= 1;
clkin_ps_mkup <= 0;
end
end
end
else begin
clkin_ps_mkup_win <= 0;
clkin_ps_mkup <= 0;
end
ps_delay_last <= ps_delay;
end
end
 
always @(clkin_ps or lock_fb)
clkin_fb = clkin_ps & lock_fb;
 
always @(negedge clkfb_in or posedge rst_in)
if (rst_in)
clkfb_div_en <= 0;
else
if (lock_fb_dly && lock_period && lock_fb && ~clkin_ps)
clkfb_div_en <= 1;
 
always @(posedge clkfb_in or posedge rst_in)
if (rst_in)
clkfb_div <= 0;
else
if (clkfb_div_en )
clkfb_div <= ~clkfb_div;
 
always @(clkfb_in or clkfb_div )
if (clkfb_type == 2'b10 )
clkfb_chk = clkfb_div;
else
clkfb_chk = clkfb_in & lock_fb_dly;
 
always @(posedge clkin_fb or posedge chk_rst)
if (chk_rst)
clkin_chkin <= 0;
else
clkin_chkin <= 1;
 
always @(posedge clkfb_chk or posedge chk_rst)
if (chk_rst)
clkfb_chkin <= 0;
else
clkfb_chkin <= 1;
 
assign chk_rst = (rst_in==1 || clock_stopped==1 ) ? 1 : 0;
assign chk_enable = (clkin_chkin == 1 && clkfb_chkin == 1 &&
lock_ps ==1 && lock_fb ==1 && lock_fb_dly == 1) ? 1 : 0;
 
always @(posedge clkin_div or posedge rst_in)
if (rst_in) begin
period_div <= 0;
clkin_div_edge <= 0;
end
else
if ( clkin_div ==1 ) begin
clkin_div_edge <= $time;
if (($time - clkin_div_edge) <= (1.5 * period_div))
period_div <= $time - clkin_div_edge;
else if ((period_div == 0) && (clkin_div_edge != 0))
period_div <= $time - clkin_div_edge;
end
 
always @(posedge clkin_ps or posedge rst_in)
if (rst_in) begin
period_ps <= 0;
clkin_ps_edge <= 0;
end
else
if (clkin_ps == 1 ) begin
clkin_ps_edge <= $time;
if (($time - clkin_ps_edge) <= (1.5 * period_ps))
period_ps <= $time - clkin_ps_edge;
else if ((period_ps == 0) && (clkin_ps_edge != 0))
period_ps <= $time - clkin_ps_edge;
end
 
always @(posedge clkin_ps) begin
lock_ps <= lock_period;
lock_ps_dly <= lock_ps;
lock_fb <= lock_ps_dly;
lock_fb_dly_tmp <= lock_fb;
end
 
always @(negedge clkin_ps or posedge rst_in)
if (rst_in)
lock_fb_dly <= 1'b0;
else
lock_fb_dly <= #(period/4) lock_fb_dly_tmp;
 
 
always @(period or fb_delay )
if (fb_delay == 0)
clkout_delay = 0;
else
clkout_delay = period - fb_delay;
 
//
// generate master reset signal
//
 
always @(posedge clkin_in) begin
rst_reg[0] <= rst_in;
rst_reg[1] <= rst_reg[0] & rst_in;
rst_reg[2] <= rst_reg[1] & rst_reg[0] & rst_in;
end
 
reg rst_tmp1, rst_tmp2;
initial
begin
rst_tmp1 = 0;
rst_tmp2 = 0;
rst_flag = 0;
end
 
always @(rst_in)
begin
if (rst_in)
rst_flag = 0;
 
rst_tmp1 = rst_in;
if (rst_tmp1 == 0 && rst_tmp2 == 1) begin
if ((rst_reg[2] & rst_reg[1] & rst_reg[0]) == 0) begin
rst_flag = 1;
$display("Input Error : RST on instance %m must be asserted for 3 CLKIN clock cycles.");
end
end
rst_tmp2 = rst_tmp1;
end
 
initial begin
CLK0 = 0;
CLK180 = 0;
CLK270 = 0;
CLK2X = 0;
CLK2X180 = 0;
CLK90 = 0;
CLKDV = 0;
CLKFX = 0;
CLKFX180 = 0;
clk0_out = 0;
clk2x_out = 0;
clkdv_out = 0;
clkdv_cnt = 0;
clkfb_window = 0;
clkfx_out = 0;
clkfx180_en = 0;
clkin_div_edge = 0;
clkin_period[0] = 0;
clkin_period[1] = 0;
clkin_period[2] = 0;
clkin_edge = 0;
clkin_ps_edge = 0;
clkin_window = 0;
clkout_delay = 0;
clock_stopped = 1;
fb_delay = 0;
fb_delay_found = 0;
lock_clkfb = 0;
lock_clkin = 0;
lock_delay = 0;
lock_fb = 0;
lock_fb_dly = 0;
lock_out = 2'b00;
lock_out1_neg = 0;
lock_period = 0;
lock_ps = 0;
lock_ps_dly = 0;
locked_out = 0;
period = 0;
period_int = 0;
period_int2 = 0;
period_int3 = 0;
period_div = 0;
period_fx = 0;
period_orig = 0;
period_orig_int = 0;
period_ps = 0;
psdone_out = 0;
ps_delay = 0;
ps_delay_md = 0;
ps_delay_init = 0;
ps_acc = 0;
ps_delay_all = 0;
ps_lock = 0;
ps_overflow_out = 0;
ps_overflow_out_ext = 0;
clkin_lost_out_ext = 0;
clkfx_lost_out_ext = 0;
rst_reg = 3'b000;
first_time_locked = 0;
en_status = 0;
clkfb_div = 0;
clkin_chkin = 0;
clkfb_chkin = 0;
clkin_ps_mkup = 0;
clkin_ps_mkup_win = 0;
clkin_ps_mkup_flag = 0;
ps_delay_last = 0;
clkin_ps_tmp = 0;
end
 
// RST less than 3 cycles, lock = x
 
assign locked_out_out = (rst_flag) ? 1'bx : locked_out;
 
//
// detect_first_time_locked
//
always @(posedge locked_out)
if (first_time_locked == 0)
first_time_locked <= 1;
 
//
// phase shift parameters
//
 
always @(posedge lock_period)
ps_delay_init <= ps_in * period_orig /256;
 
 
always @(period) begin
period_int = period;
if (clkin_type==1)
period_ps_tmp = 2 * period;
else
period_ps_tmp = period;
 
if (period_ps_tmp > 3000)
ps_max_range = 20 * (period_ps_tmp - 3000)/1000;
else
ps_max_range = 0;
end
 
always @(ps_delay or rst_in or period_int or lock_period)
if ( rst_in)
ps_delay_md = 0;
else if (lock_period) begin
ps_delay_md = period_int + ps_delay % period_int;
end
 
always @(posedge psclk_in or posedge rst_in or posedge lock_period_pulse)
if (rst_in) begin
ps_delay <= 0;
ps_overflow_out <= 0;
ps_acc <= 0;
end
else if (lock_period_pulse)
ps_delay <= ps_delay_init;
else
if (ps_type == 2'b10)
if (psen_in) begin
if (ps_lock == 1)
$display(" Warning : Please wait for PSDONE signal before adjusting the Phase Shift.");
else if (lock_ps) begin
if (psincdec_in == 1) begin
if (ps_acc > ps_max_range)
ps_overflow_out <= 1;
else begin
ps_delay <= ps_delay + PS_STEP;
ps_acc <= ps_acc + 1;
ps_overflow_out <= 0;
end
ps_lock <= 1;
end
else if (psincdec_in == 0) begin
if (ps_acc < -ps_max_range)
ps_overflow_out <= 1;
else begin
ps_delay <= ps_delay - PS_STEP;
ps_acc <= ps_acc - 1;
ps_overflow_out <= 0;
end
ps_lock <= 1;
end
end
end
 
always @(posedge ps_lock) begin
@(posedge clkin_ps)
@(posedge psclk_in)
@(posedge psclk_in)
@(posedge psclk_in)
psdone_out <= 1;
@(posedge psclk_in)
psdone_out <= 0;
ps_lock <= 0;
end
 
//
// determine clock period
//
 
always @(posedge clkin_div or negedge clkin_div or posedge rst_in)
if (rst_in == 1) begin
clkin_period[0] <= 0;
clkin_period[1] <= 0;
clkin_period[2] <= 0;
clkin_edge <= 0;
end
else
if (clkin_div == 1) begin
clkin_edge <= $time;
clkin_period[2] <= clkin_period[1];
clkin_period[1] <= clkin_period[0];
if (clkin_edge != 0)
clkin_period[0] <= $time - clkin_edge;
end
else if (clkin_div == 0)
if (lock_period == 1)
if (100000000 < clkin_period[0]/1000)
begin
end
else if ((period_orig * 2 < clkin_period[0]) && (clock_stopped == 0)) begin
clkin_period[0] <= clkin_period[1];
end
 
always @(negedge clkin_div or posedge rst_in)
if (rst_in == 1) begin
lock_period <= 0;
clock_stopped <= 1;
end
else begin
if (lock_period == 1'b0) begin
if ((clkin_period[0] != 0) &&
(clkin_period[0] - cycle_jitter <= clkin_period[1]) &&
(clkin_period[1] <= clkin_period[0] + cycle_jitter) &&
(clkin_period[1] - cycle_jitter <= clkin_period[2]) &&
(clkin_period[2] <= clkin_period[1] + cycle_jitter)) begin
lock_period <= 1;
period_orig <= (clkin_period[0] +
clkin_period[1] +
clkin_period[2]) / 3;
period <= clkin_period[0];
end
end
else if (lock_period == 1'b1) begin
if (100000000 < (clkin_period[0] / 1000)) begin
$display(" Warning : CLKIN stopped toggling on instance %m exceeds %d ms. Current CLKIN Period = %1.3f ns.", 100, clkin_period[0] / 1000.0);
lock_period <= 0;
@(negedge rst_reg[2]);
end
else if ((period_orig * 2 < clkin_period[0]) && clock_stopped == 1'b0) begin
clock_stopped <= 1'b1;
end
else if ((clkin_period[0] < period_orig - period_jitter) ||
(period_orig + period_jitter < clkin_period[0])) begin
$display(" Warning : Input Clock Period Jitter on instance %m exceeds %1.3f ns. Locked CLKIN Period = %1.3f. Current CLKIN Period = %1.3f.", period_jitter / 1000.0, period_orig / 1000.0, clkin_period[0] / 1000.0);
lock_period <= 0;
@(negedge rst_reg[2]);
end
else if ((clkin_period[0] < clkin_period[1] - cycle_jitter) ||
(clkin_period[1] + cycle_jitter < clkin_period[0])) begin
$display(" Warning : Input Clock Cycle-Cycle Jitter on instance %m exceeds %1.3f ns. Previous CLKIN Period = %1.3f. Current CLKIN Period = %1.3f.", cycle_jitter / 1000.0, clkin_period[1] / 1000.0, clkin_period[0] / 1000.0);
lock_period <= 0;
@(negedge rst_reg[2]);
end
else begin
period <= clkin_period[0];
clock_stopped <= 1'b0;
end
end
end
 
assign #1 lock_period_dly1 = lock_period;
assign #(period/2) lock_period_dly = lock_period_dly1;
assign lock_period_pulse = (lock_period_dly1==1 && lock_period_dly==0) ? 1 : 0;
 
//
// determine clock delay
//
 
//always @(posedge lock_period or posedge rst_in)
always @(posedge lock_ps_dly or posedge rst_in)
if (rst_in) begin
fb_delay <= 0;
fb_delay_found <= 0;
end
else begin
if (lock_period && clkfb_type != 2'b00) begin
if (clkfb_type == 2'b01) begin
@(posedge CLK0 or rst_in)
delay_edge = $time;
end
else if (clkfb_type == 2'b10) begin
@(posedge CLK2X or rst_in)
delay_edge = $time;
end
@(posedge clkfb_in or rst_in) begin
fb_delay <= ($time - delay_edge) % period_orig;
fb_delay_found <= 1;
end
end
end
 
//
// determine feedback lock
//
 
always @(posedge clkfb_chk or posedge rst_in)
if (rst_in)
clkfb_window <= 0;
else begin
clkfb_window <= 1;
#cycle_jitter clkfb_window <= 0;
end
 
always @(posedge clkin_fb or posedge rst_in)
if (rst_in)
clkin_window <= 0;
else begin
clkin_window <= 1;
#cycle_jitter clkin_window <= 0;
end
 
always @(posedge clkin_fb or posedge rst_in)
if (rst_in)
lock_clkin <= 0;
else begin
#1
if ((clkfb_window && fb_delay_found) || (clkin_lost_out == 1'b1 && lock_out[0]==1'b1))
lock_clkin <= 1;
else
if (chk_enable==1)
lock_clkin <= 0;
end
 
always @(posedge clkfb_chk or posedge rst_in)
if (rst_in)
lock_clkfb <= 0;
else begin
#1
if ((clkin_window && fb_delay_found) || (clkin_lost_out == 1'b1 && lock_out[0]==1'b1))
lock_clkfb <= 1;
else
if (chk_enable ==1)
lock_clkfb <= 0;
end
 
always @(negedge clkin_fb or posedge rst_in)
if (rst_in)
lock_delay <= 0;
else
lock_delay <= lock_clkin || lock_clkfb;
 
//
// generate lock signal
//
 
always @(posedge clkin_ps or posedge rst_in)
if (rst_in) begin
lock_out <= 2'b0;
locked_out <=0;
end
else begin
if (clkfb_type == 2'b00)
lock_out[0] <= lock_period;
else
lock_out[0] <= lock_period & lock_delay & lock_fb;
lock_out[1] <= lock_out[0];
locked_out <= lock_out[1];
end
 
always @(negedge clkin_ps or posedge rst_in)
if (rst_in)
lock_out1_neg <= 0;
else
lock_out1_neg <= lock_out[1];
 
 
//
// generate the clk1x_out
//
 
always @(posedge clkin_ps or negedge clkin_ps or posedge rst_in)
if (rst_in)
clk0_out <= 0;
else
if (clkin_ps ==1)
if (clk1x_type==1 && lock_out[0]) begin
clk0_out <= 1;
#(period / 2)
clk0_out <= 0;
end
else
clk0_out <= 1;
else
if (clkin_ps == 0 && ((clk1x_type && lock_out[0]) == 0 || (lock_out[0]== 1 && lock_out[1]== 0)))
clk0_out <= 0;
 
//
// generate the clk2x_out
//
 
always @(posedge clkin_ps or posedge rst_in)
if (rst_in)
clk2x_out <= 0;
else begin
clk2x_out <= 1;
#(period / 4)
clk2x_out <= 0;
#(period / 4)
clk2x_out <= 1;
#(period / 4)
clk2x_out <= 0;
end
 
//
// generate the clkdv_out
//
 
always @(posedge clkin_ps or negedge clkin_ps or posedge rst_in)
if (rst_in) begin
clkdv_out <= 1'b0;
clkdv_cnt <= 0;
end
else
if (lock_out1_neg) begin
if (clkdv_cnt >= divide_type -1)
clkdv_cnt <= 0;
else
clkdv_cnt <= clkdv_cnt + 1;
 
if (clkdv_cnt < divide_type /2)
clkdv_out <= 1'b1;
else
if ( (divide_type[0] == 1'b1) && dll_mode_type == 1'b0)
clkdv_out <= #(period/4) 1'b0;
else
clkdv_out <= 1'b0;
end
 
 
//
// generate fx output signal
//
 
always @(lock_period or period or denominator or numerator) begin
if (lock_period == 1'b1) begin
period_fx = (period * denominator) / (numerator * 2);
remain_fx = (period * denominator) % (numerator * 2);
end
end
 
always @(posedge clkin_ps or posedge clkin_lost_out or posedge rst_in )
if (rst_in == 1)
clkfx_out = 1'b0;
else if (clkin_lost_out == 1'b1 ) begin
if (locked_out == 1)
@(negedge rst_reg[2]);
end
else
if (lock_out[1] == 1) begin
clkfx_out = 1'b1;
for (p = 0; p < (numerator * 2 - 1); p = p + 1) begin
#(period_fx);
if (p < remain_fx)
#1;
clkfx_out = !clkfx_out;
end
if (period_fx > (period / 2)) begin
#(period_fx - (period / 2));
end
end
 
//
// generate all output signal
//
 
always @(rst_in)
if (rst_in) begin
assign CLK0 = 0;
assign CLK90 = 0;
assign CLK180 = 0;
assign CLK270 = 0;
assign CLK2X = 0;
assign CLK2X180 =0;
assign CLKDV = 0;
assign CLKFX = 0;
assign CLKFX180 = 0;
end
else begin
deassign CLK0;
deassign CLK90;
deassign CLK180;
deassign CLK270;
deassign CLK2X;
deassign CLK2X180;
deassign CLKDV;
deassign CLKFX;
deassign CLKFX180;
end
 
always @(clk0_out) begin
CLK0 <= #(clkout_delay) clk0_out && (clkfb_type != 2'b00);
CLK90 <= #(clkout_delay + period / 4) clk0_out && !dll_mode_type && (clkfb_type != 2'b00);
CLK180 <= #(clkout_delay) ~clk0_out && (clkfb_type != 2'b00);
CLK270 <= #(clkout_delay + period / 4) ~clk0_out && !dll_mode_type && (clkfb_type != 2'b00);
end
 
always @(clk2x_out) begin
CLK2X <= #(clkout_delay) clk2x_out && !dll_mode_type && (clkfb_type != 2'b00);
CLK2X180 <= #(clkout_delay) ~clk2x_out && !dll_mode_type && (clkfb_type != 2'b00);
end
 
always @(clkdv_out)
CLKDV <= #(clkout_delay) clkdv_out && (clkfb_type != 2'b00);
 
always @(clkfx_out )
CLKFX <= #(clkout_delay) clkfx_out;
 
always @( clkfx_out or first_time_locked or locked_out)
if ( ~first_time_locked)
CLKFX180 = 0;
else
CLKFX180 <= #(clkout_delay) ~clkfx_out;
 
 
endmodule
 
//////////////////////////////////////////////////////
 
module dcm_sp_clock_divide_by_2 (clock, clock_type, clock_out, rst);
input clock;
input clock_type;
input rst;
output clock_out;
 
reg clock_out;
reg clock_div2;
reg [2:0] rst_reg;
wire clk_src;
 
initial begin
clock_out = 1'b0;
clock_div2 = 1'b0;
end
 
always @(posedge clock)
clock_div2 <= ~clock_div2;
 
always @(posedge clock) begin
rst_reg[0] <= rst;
rst_reg[1] <= rst_reg[0] & rst;
rst_reg[2] <= rst_reg[1] & rst_reg[0] & rst;
end
 
assign clk_src = (clock_type) ? clock_div2 : clock;
 
always @(clk_src or rst or rst_reg)
if (rst == 1'b0)
clock_out = clk_src;
else if (rst == 1'b1) begin
clock_out = 1'b0;
@(negedge rst_reg[2]);
if (clk_src == 1'b1)
@(negedge clk_src);
end
 
 
endmodule
 
module dcm_sp_maximum_period_check (clock, rst);
parameter clock_name = "";
parameter maximum_period = 0;
input clock;
input rst;
 
time clock_edge;
time clock_period;
 
initial begin
clock_edge = 0;
clock_period = 0;
end
 
always @(posedge clock) begin
clock_edge <= $time;
// clock_period <= $time - clock_edge;
clock_period = $time - clock_edge;
if (clock_period > maximum_period ) begin
if (rst == 0)
$display(" Warning : Input clock period of %1.3f ns, on the %s port of instance %m exceeds allowed value of %1.3f ns at time %1.3f ns.", clock_period/1000.0, clock_name, maximum_period/1000.0, $time/1000.0);
end
end
endmodule
 
module dcm_sp_clock_lost (clock, enable, lost, rst);
input clock;
input enable;
input rst;
output lost;
 
time clock_edge;
reg [63:0] period;
reg clock_low, clock_high;
reg clock_posedge, clock_negedge;
reg lost_r, lost_f, lost;
reg clock_second_pos, clock_second_neg;
 
initial begin
clock_edge = 0;
clock_high = 0;
clock_low = 0;
lost_r = 0;
lost_f = 0;
period = 0;
clock_posedge = 0;
clock_negedge = 0;
clock_second_pos = 0;
clock_second_neg = 0;
end
 
always @(posedge clock or posedge rst)
if (rst==1)
period <= 0;
else begin
clock_edge <= $time;
if (period != 0 && (($time - clock_edge) <= (1.5 * period)))
period <= $time - clock_edge;
else if (period != 0 && (($time - clock_edge) > (1.5 * period)))
period <= 0;
else if ((period == 0) && (clock_edge != 0) && clock_second_pos == 1)
period <= $time - clock_edge;
end
 
 
always @(posedge clock or posedge rst)
if (rst)
lost_r <= 0;
else
if (enable == 1 && clock_second_pos == 1) begin
#1;
if ( period != 0)
lost_r <= 0;
#((period * 9.1) / 10)
if ((clock_low != 1'b1) && (clock_posedge != 1'b1) && rst == 0)
lost_r <= 1;
end
 
always @(posedge clock or negedge clock or posedge rst)
if (rst) begin
clock_second_pos <= 0;
clock_second_neg <= 0;
end
else if (clock)
clock_second_pos <= 1;
else if (~clock)
clock_second_neg <= 1;
 
always @(negedge clock or posedge rst)
if (rst==1) begin
lost_f <= 0;
end
else begin
if (enable == 1 && clock_second_neg == 1) begin
if ( period != 0)
lost_f <= 0;
#((period * 9.1) / 10)
if ((clock_high != 1'b1) && (clock_negedge != 1'b1) && rst == 0)
lost_f <= 1;
end
end
 
always @( lost_r or lost_f or enable)
begin
if (enable == 1)
lost = lost_r | lost_f;
else
lost = 0;
end
 
 
always @(posedge clock or negedge clock or posedge rst)
if (rst==1) begin
clock_low <= 1'b0;
clock_high <= 1'b0;
clock_posedge <= 1'b0;
clock_negedge <= 1'b0;
end
else begin
if (clock ==1) begin
clock_low <= 1'b0;
clock_high <= 1'b1;
clock_posedge <= 1'b0;
clock_negedge <= 1'b1;
end
else if (clock == 0) begin
clock_low <= 1'b1;
clock_high <= 1'b0;
clock_posedge <= 1'b1;
clock_negedge <= 1'b0;
end
end
 
 
endmodule
/trunk/hdl/behav/xilinx_unisim/FDDRRSE.v
0,0 → 1,102
// $Header: /home/marcus/revision_ctrl_test/oc_cvs/cvs/m1_core/hdl/behav/xilinx_unisim/FDDRRSE.v,v 1.1 2008-11-07 13:12:06 fafa1971 Exp $
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 1995/2004 Xilinx, Inc.
// All Right Reserved.
///////////////////////////////////////////////////////////////////////////////
// ____ ____
// / /\/ /
// /___/ \ / Vendor : Xilinx
// \ \ \/ Version : 8.1i (I.27)
// \ \ Description : Xilinx Functional Simulation Library Component
// / / Dual Data Rate D Flip-Flop with Synchronous Reset and Set and Clock Enable
// /___/ /\ Filename : FDDRRSE.v
// \ \ / \ Timestamp : Thu Mar 25 16:42:16 PST 2004
// \___\/\___\
//
// Revision:
// 03/23/04 - Initial version.
// 02/04/05 - Rev 0.0.1 Remove input/output bufs; Seperate GSR from clock block.
// 05/06/05 - Remove internal input data strobe and add to the output. (CR207678)
// 10/20/05 - Add set & reset check to main block. (CR219794)
// 10/28/05 - combine strobe block and data block. (CR220298).
// 2/07/06 - Remove set & reset from main block and add specify block (CR225119)
// 2/10/06 - Change Q from reg to wire (CR 225613)
// End Revision
 
`timescale 1 ps / 1 ps
 
 
module FDDRRSE (Q, C0, C1, CE, D0, D1, R, S);
 
parameter INIT = 1'h0;
 
output Q;
 
input C0, C1, CE, D0, D1, R, S;
 
wire Q;
reg q_out;
 
reg q0_out, q1_out;
reg C0_tmp, C1_tmp;
 
initial begin
q_out = INIT;
q0_out = INIT;
q1_out = INIT;
C0_tmp = 0;
C1_tmp = 0;
end
 
assign Q = q_out;
 
always @(posedge C0)
if (CE == 1 || R == 1 || S == 1) begin
C0_tmp <= 1;
C0_tmp <= #100 0;
end
 
always @(posedge C1)
if (CE == 1 || R == 1 || S == 1) begin
C1_tmp <= 1;
C1_tmp <= #100 0;
end
 
always @(posedge C0)
if (R)
q0_out <= 0;
else if (S)
q0_out <= 1;
else if (CE)
q0_out <= D0;
 
always @(posedge C1)
if (R)
q1_out <= 0;
else if (S)
q1_out <= 1;
else if (CE)
q1_out <= D1;
 
always @(posedge C0_tmp or posedge C1_tmp )
if (C1_tmp)
q_out = q1_out;
else
q_out = q0_out;
 
specify
if (R)
(posedge C0 => (Q +: 1'b0)) = (100, 100);
if (!R && S)
(posedge C0 => (Q +: 1'b1)) = (100, 100);
if (!R && !S && CE)
(posedge C0 => (Q +: D0)) = (100, 100);
if (R)
(posedge C1 => (Q +: 1'b0)) = (100, 100);
if (!R && S)
(posedge C1 => (Q +: 1'b1)) = (100, 100);
if (!R && !S && CE)
(posedge C1 => (Q +: D1)) = (100, 100);
endspecify
 
endmodule
/trunk/hdl/behav/ps2_keyboard_model/ps2_keyboard_model.v
0,0 → 1,299
//////////////////////////////////////////////////////////////////////
//// ////
//// ps2_keyboard_model.v ////
//// ////
//// This file is part of the "ps2" project ////
//// http://www.opencores.org/cores/ps2/ ////
//// ////
//// Author(s): ////
//// - mihad@opencores.org ////
//// - Miha Dolenc ////
//// ////
//// All additional information is avaliable in the README.txt ////
//// file. ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org ////
//// ////
//// 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 source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.3 2003/10/03 10:16:50 primozs
// support for configurable devider added
//
// Revision 1.2 2002/04/09 13:15:16 mihad
// Wrong acknowledge generation during receiving repaired
//
// Revision 1.1.1.1 2002/02/18 16:16:55 mihad
// Initial project import - working
//
//
 
`include "timescale.v"
 
module ps2_keyboard_model
(
kbd_clk_io,
kbd_data_io,
last_char_received_o,
char_valid_o
);
 
parameter [31:0] kbd_clk_period = 50000; // chould be between 33 and 50 us to generate the clock between 30 and 20 kHz
 
inout kbd_clk_io,
kbd_data_io ;
 
output [7:0] last_char_received_o ;
reg [7:0] last_char_received_o ;
 
output char_valid_o ;
reg char_valid_o ;
 
reg kbd_clk,
kbd_data ;
 
assign kbd_clk_io = kbd_clk ? 1'bz : 1'b0 ;
assign kbd_data_io = kbd_data ? 1'bz : 1'b0 ;
 
reg receiving ;
initial
begin
kbd_clk = 1'b1 ;
kbd_data = 1'b1 ;
 
last_char_received_o = 0 ;
char_valid_o = 0 ;
 
receiving = 0 ;
end
 
always@(kbd_data_io or kbd_clk_io)
begin
// check if host is driving keyboard data low and doesn't drive clock
if ( !kbd_data_io && kbd_data && kbd_clk_io)
begin
// wait for half of clock period
#(kbd_clk_period/2) ;
 
// state hasn't changed - host wishes to send data - go receiving
if ( !kbd_data_io && kbd_data && kbd_clk_io)
kbd_receive_char(last_char_received_o) ;
end
end
 
task kbd_send_char ;
input [7:0] char ;
output transmited_ok ;
output severe_error ;
reg [10:0] tx_reg ;
integer i ;
begin:main
severe_error = 1'b0 ;
transmited_ok = 1'b0 ;
 
wait ( !receiving ) ;
 
tx_reg = { 1'b1, !(^char), char, 1'b0 } ;
 
fork
begin:wait_for_idle
wait( (kbd_clk_io === 1'b1) && (kbd_data_io === 1'b1) ) ;
// disable timeout ;
end
/*begin:timeout
#(256 * kbd_clk_period) ;
$display("Error! Keyboard bus did not go idle in 256 keyboard clock cycles time!") ;
severe_error = 1'b1 ;
transmited_ok = 1'b0 ;
disable main ;
end*/
join
 
#(kbd_clk_period/2) ;
if ( !kbd_clk_io )
begin
transmited_ok = 1'b0 ;
kbd_data = 1'b1 ;
disable main ;
end
 
i = 0 ;
while ( i < 11 )
begin
kbd_data = tx_reg[i] ;
 
#(kbd_clk_period/2) ;
 
if ( !kbd_clk_io )
begin
transmited_ok = 1'b0 ;
kbd_data = 1'b1 ;
disable main ;
end
 
kbd_clk = 1'b0 ;
 
i = i + 1 ;
 
#(kbd_clk_period/2) ;
kbd_clk = 1'b1 ;
end
 
if ( i == 11 )
transmited_ok = 1'b1 ;
end
endtask // kbd_send_char
 
task kbd_receive_char;
output [7:0] char ;
reg parity ;
integer i ;
reg stop_clocking ;
begin:main
i = 0 ;
receiving = 1 ;
stop_clocking = 1'b0 ;
 
#(kbd_clk_period/2) ;
 
while ( !stop_clocking )
begin
 
if ( !kbd_clk_io )
begin
receiving = 0 ;
disable main ;
end
 
kbd_clk = 1'b0 ;
 
#(kbd_clk_period/2) ;
 
kbd_clk = 1'b1 ;
 
if ( i > 0 )
begin
if ( i <= 8 )
char[i - 1] = kbd_data_io ;
else if ( i == 9 )
begin
parity = kbd_data_io ;
if ( parity !== ( !(^char) ) )
$display("Invalid parity bit received") ;
end
end
 
i = i + 1 ;
#(kbd_clk_period/4) ;
if ( i > 9 )
begin
if ( kbd_data_io === 1'b1 )
begin
kbd_data <= 1'b0 ;
stop_clocking = 1'b1 ;
end
end
 
#(kbd_clk_period/4) ;
end
 
kbd_clk = 1'b0 ;
 
#(kbd_clk_period/2) ;
kbd_clk <= 1'b1 ;
kbd_data <= 1'b1 ;
 
receiving = 0 ;
 
if ( i === 10 )
begin
char_valid_o = !char_valid_o ;
end
end
endtask // kbd_receive_char
 
 
time last_clk_low;
time last_clk_diference;
 
 
 
initial
begin
last_clk_low =0;
last_clk_diference =0;
 
end
 
always @(negedge kbd_clk_io)
begin:low_time_check
if (kbd_clk == 1)
begin
last_clk_low =$time;
fork
begin
#61000
$display(" clock low more then 61us");
$display("Time %t", $time) ;
#30000
$display("error clock low more then 90usec");
$display("Time %t", $time) ;
$stop;
end
begin
@(posedge kbd_clk_io);
disable low_time_check;
end
join
end
end
 
 
always @(posedge kbd_clk_io )
begin
if (last_clk_low >0 )
begin
last_clk_diference = $time - last_clk_low;
if (last_clk_diference < 60000)
begin
$display("error time< 60u");
#100 $stop;
end
end
end
 
 
 
 
 
 
endmodule // ps2_keyboard_model
/trunk/hdl/behav/ps2_keyboard_model/timescale.v
0,0 → 1,299
`timescale 1ns/1ps
/trunk/hdl/behav/ddr_model/ddr_parameters.vh
0,0 → 1,63
/****************************************************************************************
*
* Disclaimer This software code and all associated documentation, comments or other
* of Warranty: information (collectively "Software") is provided "AS IS" without
* warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY
* DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES
* OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT
* WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE
* OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE.
* FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR
* THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS,
* ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE
* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI,
* ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT,
* INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING,
* WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION,
* OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE
* THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGES. Because some jurisdictions prohibit the exclusion or
* limitation of liability for consequential or incidental damages, the
* above limitation may not apply to you.
*
* Copyright 2003 Micron Technology, Inc. All rights reserved.
*
****************************************************************************************/
 
// Timing parameters based on Speed Grade
 
// SYMBOL UNITS DESCRIPTION
// ------ ----- -----------
 
// `ifdef sg6T // Timing Parameters for -6T (CL = 2.5)
parameter tCK = 6.0; // tCK ns Nominal Clock Cycle Time
parameter tDQSQ = 0.45; // tDQSS ns DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter tMRD = 12.0; // tMRD ns Load Mode Register command cycle time
parameter tRAP = 15.0; // tRAP ns ACTIVE to READ with Auto precharge command
parameter tRAS = 42.0; // tRAS ns Active to Precharge command time
parameter tRC = 60.0; // tRC ns Active to Active/Auto Refresh command time
parameter tRFC = 120.0; // tRFC ns Refresh to Refresh Command interval time
parameter tRCD = 15.0; // tRCD ns Active to Read/Write command time
parameter tRP = 15.0; // tRP ns Precharge command period
parameter tRRD = 12.0; // tRRD ns Active bank a to Active bank b command time
parameter tWR = 15.0; // tWR ns Write recovery time
 
 
 
// Size Parameters based on Part Width
 
 
//`else `define x16
parameter ADDR_BITS = 13; // Set this parameter to control how many Address bits are used
parameter DQ_BITS = 16; // Set this parameter to control how many Data bits are used
parameter DQS_BITS = 2; // Set this parameter to control how many DQS bits are used
parameter DM_BITS = 2; // Set this parameter to control how many DM bits are used
parameter COL_BITS = 10; // Set this parameter to control how many Column bits are used
 
parameter full_mem_bits = 2+ADDR_BITS+COL_BITS; // Set this parameter to control how many unique addresses are used
parameter part_mem_bits = 10; // Set this parameter to control how many unique addresses are used
 
parameter no_halt = 0; // If set to 1, the model won't halt on command sequence/major errors
parameter Debug = 1; // Turn on debug message
 
/trunk/hdl/behav/ddr_model/readme.txt
0,0 → 1,44
********************************************************************************************
The sim folder has sample test_bench files to simulate the designs in Modelsim environment.
This folder has the memory model, test bench, glbl file and required parameter files.
Read the steps in this file before simulations are done.
 
To run simulations for this sample configuration, user has to generate the RTL from the tool for the following GUI
options.
 
Data_width : 64
HDL : Verilog or VHDL
Memory configuration : x16
DIMM/Component : Component
Memory Part No : MT46V16M16XX-5
Add test bench : Yes
Use DCM : Yes
Number of controllers : 1
Number of Write pipelines : 4
 
-----------------------------------------------For Verilog or VHDL----------------------------------------------------------
1. After the rtl is generated, create the Model sim project file. Add all the rtl files from the rtl folder
to the project Also add the memory model, test bench and glbl files from the sim folder.
 
2. Compile the design.
 
3. After successful compilation of design load the design using the following comamnd.
 
vsim -t ps +notimingchecks -L ../Modeltech_6.1a/unisims_ver work.ddr1_test_tb glbl
Note : User should set proper path for unisim verilog libraries
 
4. After the design is successfully loaded, run the simulations and view the waveforms.
 
 
Notes :
 
1. To run simulations for different data widths and configurations, users should modify the test bench files
with right memory models and design files.
 
2. User must manually change the frequency of the test bench for proper simulations.
3. Users should modify the test bench files for without test bench case.
 
 
/trunk/hdl/behav/ddr_model/ddr.v
0,0 → 1,1379
/****************************************************************************************
*
* File Name: ddr.v
* Version: 5.7
* Model: BUS Functional
*
* Dependencies: ddr_parameters.v
*
* Description: Micron SDRAM DDR (Double Data Rate)
*
* Limitation: - Doesn't check for 8K-cycle refresh.
* - Doesn't check power-down entry/exit
* - Doesn't check self-refresh entry/exit.
*
* Note: - Set simulator resolution to "ps" accuracy
* - Set Debug = 0 to disable $display messages
* - Model assume Clk and Clk# crossing at both edge
*
* Disclaimer This software code and all associated documentation, comments or other
* of Warranty: information (collectively "Software") is provided "AS IS" without
* warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY
* DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES
* OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT
* WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE
* OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE.
* FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR
* THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS,
* ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE
* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI,
* ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT,
* INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING,
* WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION,
* OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE
* THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGES. Because some jurisdictions prohibit the exclusion or
* limitation of liability for consequential or incidental damages, the
* above limitation may not apply to you.
*
* Copyright 2003 Micron Technology, Inc. All rights reserved.
*
* Rev Author Date Changes
* --- ------ ---------- ---------------------------------------
* 2.1 SPH 03/19/2002 - Second Release
* - Fix tWR and several incompatability
* between different simulators
* 3.0 TFK 02/18/2003 - Added tDSS and tDSH timing checks.
* - Added tDQSH and tDQSL timing checks.
* 3.1 CAH 05/28/2003 - update all models to release version 3.1
* (no changes to this model)
* 3.2 JMK 06/16/2003 - updated all DDR400 models to support CAS Latency 3
* 3.3 JMK 09/11/2003 - Added initialization sequence checks.
* 4.0 JMK 12/01/2003 - Grouped parameters into "ddr_parameters.v"
* - Fixed tWTR check
* 4.1 JMK 01/14/2004 - Grouped specify parameters by speed grade
* - Fixed mem_sizes parameter
* 4.2 JMK 03/19/2004 - Fixed pulse width checking on Dqs
* 4.3 JMK 04/27/2004 - Changed BL wire size in tb module
* - Changed Dq_buf size to [15:0]
* 5.0 JMK 06/16/2004 - Added read to write checking.
* - Added read with precharge truncation to write checking.
* - Added associative memory array to reduce memory consumption.
* - Added checking for required DQS edges during write.
* 5.1 JMK 08/16/2004 - Fixed checking for required DQS edges during write.
* - Fixed wdqs_valid window.
* 5.2 JMK 09/24/2004 - Read or Write without activate will be ignored.
* 5.3 JMK 10/27/2004 - Added tMRD checking during Auto Refresh and Activate.
* - Added tRFC checking during Load Mode and Precharge.
* 5.4 JMK 12/13/2004 - The model will not respond to illegal command sequences.
* 5.5 SPH 01/13/2005 - The model will issue a halt on illegal command sequences.
* JMK 02/11/2005 - Changed the display format for numbers to hex.
* 5.6 JMK 04/22/2005 - Fixed Write with auto precharge calculation.
* 5.7 JMK 08/05/2005 - Changed conditions for read with precharge truncation error.
* - Renamed parameters file with .vh extension.
****************************************************************************************/
 
// DO NOT CHANGE THE TIMESCALE
// MAKE SURE YOUR SIMULATOR USE "PS" RESOLUTION
`timescale 1ns / 1ps
 
module ddr (Dq, Dqs, Addr, Ba, Clk, Clk_n, Cke, Cs_n, Ras_n, Cas_n, We_n, Dm);
 
`include "ddr_parameters.vh"
 
// Port Declarations
inout [DQ_BITS - 1 : 0] Dq;
inout [DQS_BITS - 1 : 0] Dqs;
input [ADDR_BITS - 1 : 0] Addr;
input [1 : 0] Ba;
input Clk;
input Clk_n;
input Cke;
input Cs_n;
input Ras_n;
input Cas_n;
input We_n;
input [DM_BITS - 1 : 0] Dm;
 
// Internal Wires (fixed width)
wire [15 : 0] Dq_in;
wire [1 : 0] Dqs_in;
wire [1 : 0] Dm_in;
assign Dq_in [DQ_BITS - 1 : 0] = Dq;
assign Dqs_in [DQS_BITS - 1 : 0] = Dqs;
assign Dm_in [DM_BITS - 1 : 0] = Dm;
 
// Data pair
reg [15 : 0] dq_rise;
reg [1 : 0] dm_rise;
reg [15 : 0] dq_fall;
reg [1 : 0] dm_fall;
reg [3 : 0] dm_pair;
reg [15 : 0] Dq_buf;
// Mode Register
reg [ADDR_BITS - 1 : 0] Mode_reg;
 
// Internal System Clock
reg CkeZ, Sys_clk;
 
// Internal Dqs initialize
reg Dqs_int;
 
// Dqs buffer
reg [DQS_BITS - 1 : 0] Dqs_out;
 
// Dq buffer
reg [DQ_BITS - 1 : 0] Dq_out;
 
// Read pipeline variables
reg Read_cmnd [0 : 6];
reg [1 : 0] Read_bank [0 : 6];
reg [COL_BITS - 1 : 0] Read_cols [0 : 6];
 
// Write pipeline variables
reg Write_cmnd [0 : 3];
reg [1 : 0] Write_bank [0 : 3];
reg [COL_BITS - 1 : 0] Write_cols [0 : 3];
 
// Auto precharge variables
reg Read_precharge [0 : 3];
reg Write_precharge [0 : 3];
integer Count_precharge [0 : 3];
 
// Manual precharge variables
reg A10_precharge [0 : 6];
reg [1 : 0] Bank_precharge [0 : 6];
reg Cmnd_precharge [0 : 6];
 
// Burst terminate variables
reg Cmnd_bst [0 : 6];
 
// Memory Banks
`ifdef FULL_MEM
reg [DQ_BITS - 1 : 0] mem_array [0 : (1<<full_mem_bits)-1];
`else
reg [DQ_BITS - 1 : 0] mem_array [0 : (1<<part_mem_bits)-1];
reg [full_mem_bits - 1 : 0] addr_array [0 : (1<<part_mem_bits)-1];
reg [part_mem_bits : 0] mem_used;
initial mem_used = 0;
`endif
 
// Dqs edge checking
integer i;
reg [1:0] expect_pos_dqs;
reg [1:0] expect_neg_dqs;
 
// Burst counter
reg [COL_BITS - 1 : 0] Burst_counter;
 
// Precharge variables
reg Pc_b0, Pc_b1, Pc_b2, Pc_b3;
 
// Activate variables
reg Act_b0, Act_b1, Act_b2, Act_b3;
 
// Data IO variables
reg Data_in_enable;
reg Data_out_enable;
 
// Internal address mux variables
reg [1 : 0] Prev_bank;
reg [1 : 0] Bank_addr;
reg [COL_BITS - 1 : 0] Cols_addr, Cols_brst, Cols_temp;
reg [ADDR_BITS - 1 : 0] Rows_addr;
reg [ADDR_BITS - 1 : 0] B0_row_addr;
reg [ADDR_BITS - 1 : 0] B1_row_addr;
reg [ADDR_BITS - 1 : 0] B2_row_addr;
reg [ADDR_BITS - 1 : 0] B3_row_addr;
 
// DLL Reset variable
reg DLL_enable;
reg DLL_reset;
reg DLL_done;
integer DLL_count;
integer aref_count;
integer Prech_count;
reg power_up_done;
 
// Write DQS for tDSS, tDSH, tDQSH, tDQSL checks
wire wdqs_valid = Write_cmnd[2] || Write_cmnd[1] || Data_in_enable;
 
// 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 Ext_mode_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n & Ba[0] & ~Ba[1];
wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n & ~Ba[0] & ~Ba[1];
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 [3:0] burst_length = 1 << (Mode_reg[2:0]);
reg [3:0] read_precharge_truncation;
 
// CAS Latency Decode
// wire [2:0] cas_latency_x2 = (Mode_reg[6:4] === 3'o6) ? 5 : 2*Mode_reg[6:4];
wire [2:0] cas_latency_x2 = 5;
 
// DQS Buffer
assign Dqs = Dqs_out;
 
// DQ Buffer
assign Dq = Dq_out;
 
// Timing Check
time MRD_chk;
time RFC_chk;
time RRD_chk;
time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3;
time RAP_chk0, RAP_chk1, RAP_chk2, RAP_chk3;
time RC_chk0, RC_chk1, RC_chk2, RC_chk3;
time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3;
time RP_chk0, RP_chk1, RP_chk2, RP_chk3;
time WR_chk0, WR_chk1, WR_chk2, WR_chk3;
 
initial begin
CkeZ = 1'b0;
Sys_clk = 1'b0;
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b1111;
Dqs_int = 1'b0;
Dqs_out = {DQS_BITS{1'bz}};
Dq_out = {DQ_BITS{1'bz}};
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
DLL_enable = 1'b0;
DLL_reset = 1'b0;
DLL_done = 1'b0;
DLL_count = 0;
aref_count = 0;
Prech_count = 0;
power_up_done = 0;
MRD_chk = 0;
RFC_chk = 0;
RRD_chk = 0;
{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0;
{RAP_chk0, RAP_chk1, RAP_chk2, RAP_chk3} = 0;
{RC_chk0, RC_chk1, RC_chk2, RC_chk3} = 0;
{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0;
{RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0;
{WR_chk0, WR_chk1, WR_chk2, WR_chk3} = 0;
$timeformat (-9, 3, " ns", 12);
end
 
// System Clock
always begin
@ (posedge Clk) begin
Sys_clk = CkeZ;
CkeZ = Cke;
end
@ (negedge Clk) begin
Sys_clk = 1'b0;
end
end
 
// Check to make sure that we have a Deselect or NOP command on the bus when CKE is brought high
always @(Cke) begin
if (Cke === 1'b1) begin
if (!((Cs_n) || (~Cs_n & Ras_n & Cas_n & We_n))) begin
$display ("%m: at time %t MEMORY ERROR: You must have a Deselect or NOP command applied", $time);
$display ("%m: when the Clock Enable is brought High.");
end
end
end
 
// Check the initialization sequence
initial begin
@ (posedge Cke) begin
@ (posedge DLL_enable) begin
aref_count = 0;
@ (posedge DLL_reset) begin
@ (Prech_count) begin
if (aref_count >= 2) begin
if (Debug) $display ("%m: at time %t MEMORY: Power Up and Initialization Sequence is complete", $time);
power_up_done = 1;
end else begin
aref_count = 0;
@ (aref_count >= 2) begin
if (Debug) $display ("%m: at time %t MEMORY: Power Up and Initialization Sequence is complete", $time);
power_up_done = 1;
end
end
end
end
end
end
end
 
// Write Memory
task write_mem;
input [full_mem_bits - 1 : 0] addr;
input [DQ_BITS - 1 : 0] data;
reg [part_mem_bits : 0] i;
begin
`ifdef FULL_MEM
mem_array[addr] = data;
`else
begin : loop
for (i = 0; i < mem_used; i = i + 1) begin
if (addr_array[i] === addr) begin
disable loop;
end
end
end
if (i === mem_used) begin
if (i === (1<<part_mem_bits)) begin
$display ("At time %t ERROR: Memory overflow.\n Write to Address %h with Data %h will be lost.\n You must increase the part_mem_bits parameter or define FULL_MEM.", $time, addr, data);
end else begin
mem_used = mem_used + 1;
addr_array[i] = addr;
end
end
mem_array[i] = data;
`endif
end
endtask
 
// Read Memory
task read_mem;
input [full_mem_bits - 1 : 0] addr;
output [DQ_BITS - 1 : 0] data;
reg [part_mem_bits : 0] i;
begin
`ifdef FULL_MEM
data = mem_array[addr];
`else
begin : loop
for (i = 0; i < mem_used; i = i + 1) begin
if (addr_array[i] === addr) begin
disable loop;
end
end
end
if (i <= mem_used) begin
data = mem_array[i];
end
`endif
end
endtask
 
// Burst Decode
task Burst_Decode;
begin
 
// Advance Burst Counter
if (Burst_counter < burst_length) begin
Burst_counter = Burst_counter + 1;
end
 
// Burst Type
if (Mode_reg[3] === 1'b0) begin // Sequential Burst
Cols_temp = Cols_addr + 1;
end else if (Mode_reg[3] === 1'b1) begin // Interleaved Burst
Cols_temp[2] = Burst_counter[2] ^ Cols_brst[2];
Cols_temp[1] = Burst_counter[1] ^ Cols_brst[1];
Cols_temp[0] = Burst_counter[0] ^ Cols_brst[0];
end
 
// Burst Length
if (burst_length === 2) begin
Cols_addr [0] = Cols_temp [0];
end else if (burst_length === 4) begin
Cols_addr [1 : 0] = Cols_temp [1 : 0];
end else if (burst_length === 8) begin
Cols_addr [2 : 0] = Cols_temp [2 : 0];
end else begin
Cols_addr = Cols_temp;
end
 
// Data Counter
if (Burst_counter >= burst_length) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
read_precharge_truncation = 4'h0;
end
end
endtask
 
// Manual Precharge Pipeline
task Manual_Precharge_Pipeline;
begin
// A10 Precharge Pipeline
A10_precharge[0] = A10_precharge[1];
A10_precharge[1] = A10_precharge[2];
A10_precharge[2] = A10_precharge[3];
A10_precharge[3] = A10_precharge[4];
A10_precharge[4] = A10_precharge[5];
A10_precharge[5] = A10_precharge[6];
A10_precharge[6] = 1'b0;
 
// Bank Precharge Pipeline
Bank_precharge[0] = Bank_precharge[1];
Bank_precharge[1] = Bank_precharge[2];
Bank_precharge[2] = Bank_precharge[3];
Bank_precharge[3] = Bank_precharge[4];
Bank_precharge[4] = Bank_precharge[5];
Bank_precharge[5] = Bank_precharge[6];
Bank_precharge[6] = 2'b0;
 
// Command Precharge Pipeline
Cmnd_precharge[0] = Cmnd_precharge[1];
Cmnd_precharge[1] = Cmnd_precharge[2];
Cmnd_precharge[2] = Cmnd_precharge[3];
Cmnd_precharge[3] = Cmnd_precharge[4];
Cmnd_precharge[4] = Cmnd_precharge[5];
Cmnd_precharge[5] = Cmnd_precharge[6];
Cmnd_precharge[6] = 1'b0;
 
// Terminate a Read if same bank or all banks
if (Cmnd_precharge[0] === 1'b1) begin
if (Bank_precharge[0] === Bank_addr || A10_precharge[0] === 1'b1) begin
if (Data_out_enable === 1'b1) begin
Data_out_enable = 1'b0;
read_precharge_truncation = 4'hF;
end
end
end
end
endtask
 
// Burst Terminate Pipeline
task Burst_Terminate_Pipeline;
begin
// Command Precharge Pipeline
Cmnd_bst[0] = Cmnd_bst[1];
Cmnd_bst[1] = Cmnd_bst[2];
Cmnd_bst[2] = Cmnd_bst[3];
Cmnd_bst[3] = Cmnd_bst[4];
Cmnd_bst[4] = Cmnd_bst[5];
Cmnd_bst[5] = Cmnd_bst[6];
Cmnd_bst[6] = 1'b0;
 
// Terminate a Read regardless of banks
if (Cmnd_bst[0] === 1'b1 && Data_out_enable === 1'b1) begin
Data_out_enable = 1'b0;
end
end
endtask
 
// Dq and Dqs Drivers
task Dq_Dqs_Drivers;
begin
// read command pipeline
Read_cmnd [0] = Read_cmnd [1];
Read_cmnd [1] = Read_cmnd [2];
Read_cmnd [2] = Read_cmnd [3];
Read_cmnd [3] = Read_cmnd [4];
Read_cmnd [4] = Read_cmnd [5];
Read_cmnd [5] = Read_cmnd [6];
Read_cmnd [6] = 1'b0;
 
// read bank pipeline
Read_bank [0] = Read_bank [1];
Read_bank [1] = Read_bank [2];
Read_bank [2] = Read_bank [3];
Read_bank [3] = Read_bank [4];
Read_bank [4] = Read_bank [5];
Read_bank [5] = Read_bank [6];
Read_bank [6] = 2'b0;
 
// read column pipeline
Read_cols [0] = Read_cols [1];
Read_cols [1] = Read_cols [2];
Read_cols [2] = Read_cols [3];
Read_cols [3] = Read_cols [4];
Read_cols [4] = Read_cols [5];
Read_cols [5] = Read_cols [6];
Read_cols [6] = 0;
 
// Initialize Read command
if (Read_cmnd [0] === 1'b1) begin
Data_out_enable = 1'b1;
Bank_addr = Read_bank [0];
Cols_addr = Read_cols [0];
Cols_brst = Cols_addr [2 : 0];
Burst_counter = 0;
 
// Row Address Mux
case (Bank_addr)
2'd0 : Rows_addr = B0_row_addr;
2'd1 : Rows_addr = B1_row_addr;
2'd2 : Rows_addr = B2_row_addr;
2'd3 : Rows_addr = B3_row_addr;
default : $display ("At time %t ERROR: Invalid Bank Address", $time);
endcase
end
 
// Toggle Dqs during Read command
if (Data_out_enable === 1'b1) begin
Dqs_int = 1'b0;
if (Dqs_out === {DQS_BITS{1'b0}}) begin
Dqs_out = {DQS_BITS{1'b1}};
end else if (Dqs_out === {DQS_BITS{1'b1}}) begin
Dqs_out = {DQS_BITS{1'b0}};
end else begin
Dqs_out = {DQS_BITS{1'b0}};
end
end else if (Data_out_enable === 1'b0 && Dqs_int === 1'b0) begin
Dqs_out = {DQS_BITS{1'bz}};
end
 
// Initialize dqs for Read command
if (Read_cmnd [2] === 1'b1) begin
if (Data_out_enable === 1'b0) begin
Dqs_int = 1'b1;
Dqs_out = {DQS_BITS{1'b0}};
end
end
 
// Read latch
if (Data_out_enable === 1'b1) begin
// output data
read_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_out);
if (Debug) begin
$display ("At time %t READ : Bank = %h, Row = %h, Col = %h, Data = %h", $time, Bank_addr, Rows_addr, Cols_addr, Dq_out);
end
end else begin
Dq_out = {DQ_BITS{1'bz}};
end
end
endtask
 
// Write FIFO and DM Mask Logic
task Write_FIFO_DM_Mask_Logic;
begin
// Write command pipeline
Write_cmnd [0] = Write_cmnd [1];
Write_cmnd [1] = Write_cmnd [2];
Write_cmnd [2] = Write_cmnd [3];
Write_cmnd [3] = 1'b0;
 
// Write command pipeline
Write_bank [0] = Write_bank [1];
Write_bank [1] = Write_bank [2];
Write_bank [2] = Write_bank [3];
Write_bank [3] = 2'b0;
 
// Write column pipeline
Write_cols [0] = Write_cols [1];
Write_cols [1] = Write_cols [2];
Write_cols [2] = Write_cols [3];
Write_cols [3] = {COL_BITS{1'b0}};
 
// Initialize Write command
if (Write_cmnd [0] === 1'b1) begin
Data_in_enable = 1'b1;
Bank_addr = Write_bank [0];
Cols_addr = Write_cols [0];
Cols_brst = Cols_addr [2 : 0];
Burst_counter = 0;
 
// Row address mux
case (Bank_addr)
2'd0 : Rows_addr = B0_row_addr;
2'd1 : Rows_addr = B1_row_addr;
2'd2 : Rows_addr = B2_row_addr;
2'd3 : Rows_addr = B3_row_addr;
default : $display ("At time %t ERROR: Invalid Row Address", $time);
endcase
end
 
// Write data
if (Data_in_enable === 1'b1) begin
 
// Data Buffer
read_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_buf);
 
// write negedge Dqs on posedge Sys_clk
if (Sys_clk) begin
if (!dm_fall[0]) begin
Dq_buf [ 7 : 0] = dq_fall [ 7 : 0];
end
if (!dm_fall[1]) begin
Dq_buf [15 : 8] = dq_fall [15 : 8];
end
if (~&dm_fall) begin
if (Debug) begin
$display ("At time %t WRITE: Bank = %h, Row = %h, Col = %h, Data = %h", $time, Bank_addr, Rows_addr, Cols_addr, Dq_buf[DQ_BITS-1:0]);
end
end
// write posedge Dqs on negedge Sys_clk
end else begin
if (!dm_rise[0]) begin
Dq_buf [ 7 : 0] = dq_rise [ 7 : 0];
end
if (!dm_rise[1]) begin
Dq_buf [15 : 8] = dq_rise [15 : 8];
end
if (~&dm_rise) begin
if (Debug) begin
$display ("At time %t WRITE: Bank = %h, Row = %h, Col = %h, Data = %h", $time, Bank_addr, Rows_addr, Cols_addr, Dq_buf[DQ_BITS-1:0]);
end
end
end
 
// Write Data
write_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_buf);
 
// tWR start and tWTR check
if (Sys_clk && &dm_pair === 1'b0) begin
case (Bank_addr)
2'd0 : WR_chk0 = $time;
2'd1 : WR_chk1 = $time;
2'd2 : WR_chk2 = $time;
2'd3 : WR_chk3 = $time;
default : $display ("At time %t ERROR: Invalid Bank Address (tWR)", $time);
endcase
 
// tWTR check
if (Read_enable === 1'b1) begin
$display ("At time %t ERROR: tWTR violation during Read", $time);
end
end
end
end
endtask
 
// Auto Precharge Calculation
task Auto_Precharge_Calculation;
begin
// Precharge counter
if (Read_precharge [0] === 1'b1 || Write_precharge [0] === 1'b1) begin
Count_precharge [0] = Count_precharge [0] + 1;
end
if (Read_precharge [1] === 1'b1 || Write_precharge [1] === 1'b1) begin
Count_precharge [1] = Count_precharge [1] + 1;
end
if (Read_precharge [2] === 1'b1 || Write_precharge [2] === 1'b1) begin
Count_precharge [2] = Count_precharge [2] + 1;
end
if (Read_precharge [3] === 1'b1 || Write_precharge [3] === 1'b1) begin
Count_precharge [3] = Count_precharge [3] + 1;
end
 
// Read with AutoPrecharge Calculation
// The device start internal precharge when:
// 1. Meet tRAS requirement
// 2. BL/2 cycles after command
if ((Read_precharge[0] === 1'b1) && ($time - RAS_chk0 >= tRAS)) begin
if (Count_precharge[0] >= burst_length/2) begin
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Read_precharge[0] = 1'b0;
end
end
if ((Read_precharge[1] === 1'b1) && ($time - RAS_chk1 >= tRAS)) begin
if (Count_precharge[1] >= burst_length/2) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Read_precharge[1] = 1'b0;
end
end
if ((Read_precharge[2] === 1'b1) && ($time - RAS_chk2 >= tRAS)) begin
if (Count_precharge[2] >= burst_length/2) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Read_precharge[2] = 1'b0;
end
end
if ((Read_precharge[3] === 1'b1) && ($time - RAS_chk3 >= tRAS)) begin
if (Count_precharge[3] >= burst_length/2) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Read_precharge[3] = 1'b0;
end
end
 
// Write with AutoPrecharge Calculation
// The device start internal precharge when:
// 1. Meet tRAS requirement
// 2. Write Latency PLUS BL/2 cycles PLUS tWR after Write command
 
if ((Write_precharge[0] === 1'b1) && ($time - RAS_chk0 >= tRAS)) begin
if ((Count_precharge[0] >= burst_length/2+1) && ($time - WR_chk0 >= tWR)) begin
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Write_precharge[0] = 1'b0;
end
end
if ((Write_precharge[1] === 1'b1) && ($time - RAS_chk1 >= tRAS)) begin
if ((Count_precharge[1] >= burst_length/2+1) && ($time - WR_chk1 >= tWR)) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Write_precharge[1] = 1'b0;
end
end
if ((Write_precharge[2] === 1'b1) && ($time - RAS_chk2 >= tRAS)) begin
if ((Count_precharge[2] >= burst_length/2+1) && ($time - WR_chk2 >= tWR)) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Write_precharge[2] = 1'b0;
end
end
if ((Write_precharge[3] === 1'b1) && ($time - RAS_chk3 >= tRAS)) begin
if ((Count_precharge[3] >= burst_length/2+1) && ($time - WR_chk3 >= tWR)) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Write_precharge[3] = 1'b0;
end
end
end
endtask
 
// DLL Counter
task DLL_Counter;
begin
if (DLL_reset === 1'b1 && DLL_done === 1'b0) begin
DLL_count = DLL_count + 1;
if (DLL_count >= 200) begin
DLL_done = 1'b1;
end
end
end
endtask
 
// Control Logic
task Control_Logic;
begin
// Auto Refresh
if (Aref_enable === 1'b1) begin
// Display Debug Message
if (Debug) begin
$display ("At time %t AREF : 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
// LMR/EMR to Auto Refresh
if ($time - MRD_chk < tMRD) begin
$display ("At time %t ERROR: tMRD violation during Auto Refresh", $time);
end
 
// Auto Refresh to Auto Refresh
if ($time - RFC_chk < tRFC) begin
$display ("At time %t ERROR: tRFC violation during Auto Refresh", $time);
end
// Precharge to Auto 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 Precharged before Auto Refresh", $time);
if (!no_halt) $stop (0);
end else begin
aref_count = aref_count + 1;
RFC_chk = $time;
end
end
// Extended Mode Register
if (Ext_mode_enable === 1'b1) begin
if (Debug) begin
$display ("At time %t EMR : Extended Mode Register", $time);
end
 
// Precharge to LMR/EMR
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 Extended Mode Register", $time);
end
 
// LMR/EMR to LMR/EMR
if ($time - MRD_chk < tMRD) begin
$display ("At time %t ERROR: tMRD violation during Extended Mode Register", $time);
end
 
// Auto Refresh to LMR/EMR
if ($time - RFC_chk < tRFC) begin
$display ("At time %t ERROR: tRFC violation during Extended Mode Register", $time);
end
 
// Precharge to LMR/EMR
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 Precharged before Extended Mode Register", $time);
if (!no_halt) $stop (0);
end else begin
if (Addr[0] === 1'b0) begin
DLL_enable = 1'b1;
if (Debug) begin
$display ("At time %t EMR : Enable DLL", $time);
end
end else begin
DLL_enable = 1'b0;
if (Debug) begin
$display ("At time %t EMR : Disable DLL", $time);
end
end
MRD_chk = $time;
end
end
// Load Mode Register
if (Mode_reg_enable === 1'b1) begin
if (Debug) begin
$display ("At time %t LMR : Load Mode Register", $time);
end
 
// Precharge to LMR/EMR
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 Load Mode Register", $time);
end
 
// LMR/EMR to LMR/EMR
if ($time - MRD_chk < tMRD) begin
$display ("At time %t ERROR: tMRD violation during Load Mode Register", $time);
end
 
// Auto Refresh to LMR/EMR
if ($time - RFC_chk < tRFC) begin
$display ("At time %t ERROR: tRFC violation during Load Mode Register", $time);
end
 
// Precharge to LMR/EMR
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 Precharged before Load Mode Register", $time);
end else begin
// Register Mode
Mode_reg = Addr;
 
// DLL Reset
if (DLL_enable === 1'b1 && Addr [8] === 1'b1) begin
DLL_reset = 1'b1;
DLL_done = 1'b0;
DLL_count = 0;
end else if (DLL_enable === 1'b1 && DLL_reset === 1'b0 && Addr [8] === 1'b0) begin
$display ("At time %t ERROR: DLL is ENABLE: DLL RESET is required.", $time);
end else if (DLL_enable === 1'b0 && Addr [8] === 1'b1) begin
$display ("At time %t ERROR: DLL is DISABLE: DLL RESET will be ignored.", $time);
end
 
// Burst Length
case (Addr [2 : 0])
3'b001 : $display ("At time %t LMR : Burst Length = 2", $time);
3'b010 : $display ("At time %t LMR : Burst Length = 4", $time);
3'b011 : $display ("At time %t LMR : Burst Length = 8", $time);
default : $display ("At time %t ERROR: Burst Length not supported", $time);
endcase
 
// CAS Latency
case (Addr [6 : 4])
3'b010 : $display ("At time %t LMR : CAS Latency = 2", $time);
3'b110 : $display ("At time %t LMR : CAS Latency = 2.5", $time);
3'b011 : $display ("At time %t LMR : CAS Latency = 3", $time);
default : $display ("At time %t ERROR: CAS Latency not supported", $time);
endcase
 
// Record current tMRD time
MRD_chk = $time;
end
end
 
// Activate Block
if (Active_enable === 1'b1) begin
if (!(power_up_done)) begin
$display ("%m: at time %t ERROR: Power Up and Initialization Sequence not completed before executing Activate command", $time);
end
// Display Debug Message
if (Debug) begin
$display ("At time %t ACT : Bank = %h, Row = %h", $time, Ba, Addr);
end
 
// Activate to Activate (different bank)
if ((Prev_bank != Ba) && ($time - RRD_chk < tRRD)) begin
$display ("At time %t ERROR: tRRD violation during Activate bank %h", $time, Ba);
end
// LMR/EMR to Activate
if ($time - MRD_chk < tMRD) begin
$display ("At time %t ERROR: tMRD violation during Activate bank %h", $time, Ba);
end
 
// AutoRefresh to Activate
if ($time - RFC_chk < tRFC) begin
$display ("At time %t ERROR: tRFC violation during Activate bank %h", $time, Ba);
end
 
// Precharge to Activate
if ((Ba === 2'b00 && Pc_b0 === 1'b0) || (Ba === 2'b01 && Pc_b1 === 1'b0) ||
(Ba === 2'b10 && Pc_b2 === 1'b0) || (Ba === 2'b11 && Pc_b3 === 1'b0)) begin
$display ("At time %t ERROR: Bank = %h is already activated - Command Ignored", $time, Ba);
if (!no_halt) $stop (0);
end else begin
// Activate Bank 0
if (Ba === 2'b00 && Pc_b0 === 1'b1) begin
// Activate to Activate (same bank)
if ($time - RC_chk0 < tRC) begin
$display ("At time %t ERROR: tRC violation during Activate bank %h", $time, Ba);
end
 
// Precharge to Activate
if ($time - RP_chk0 < tRP) begin
$display ("At time %t ERROR: tRP violation during Activate bank %h", $time, Ba);
end
 
// Record variables for checking violation
Act_b0 = 1'b1;
Pc_b0 = 1'b0;
B0_row_addr = Addr;
RC_chk0 = $time;
RCD_chk0 = $time;
RAS_chk0 = $time;
RAP_chk0 = $time;
end
 
// Activate Bank 1
if (Ba === 2'b01 && Pc_b1 === 1'b1) begin
// Activate to Activate (same bank)
if ($time - RC_chk1 < tRC) begin
$display ("At time %t ERROR: tRC violation during Activate bank %h", $time, Ba);
end
 
// Precharge to Activate
if ($time - RP_chk1 < tRP) begin
$display ("At time %t ERROR: tRP violation during Activate bank %h", $time, Ba);
end
 
// Record variables for checking violation
Act_b1 = 1'b1;
Pc_b1 = 1'b0;
B1_row_addr = Addr;
RC_chk1 = $time;
RCD_chk1 = $time;
RAS_chk1 = $time;
RAP_chk1 = $time;
end
 
// Activate Bank 2
if (Ba === 2'b10 && Pc_b2 === 1'b1) begin
// Activate to Activate (same bank)
if ($time - RC_chk2 < tRC) begin
$display ("At time %t ERROR: tRC violation during Activate bank %h", $time, Ba);
end
 
// Precharge to Activate
if ($time - RP_chk2 < tRP) begin
$display ("At time %t ERROR: tRP violation during Activate bank %h", $time, Ba);
end
 
// Record variables for checking violation
Act_b2 = 1'b1;
Pc_b2 = 1'b0;
B2_row_addr = Addr;
RC_chk2 = $time;
RCD_chk2 = $time;
RAS_chk2 = $time;
RAP_chk2 = $time;
end
 
// Activate Bank 3
if (Ba === 2'b11 && Pc_b3 === 1'b1) begin
// Activate to Activate (same bank)
if ($time - RC_chk3 < tRC) begin
$display ("At time %t ERROR: tRC violation during Activate bank %h", $time, Ba);
end
 
// Precharge to Activate
if ($time - RP_chk3 < tRP) begin
$display ("At time %t ERROR: tRP violation during Activate bank %h", $time, Ba);
end
 
// Record variables for checking violation
Act_b3 = 1'b1;
Pc_b3 = 1'b0;
B3_row_addr = Addr;
RC_chk3 = $time;
RCD_chk3 = $time;
RAS_chk3 = $time;
RAP_chk3 = $time;
end
// Record variable for checking violation
RRD_chk = $time;
Prev_bank = Ba;
read_precharge_truncation[Ba] = 1'b0;
end
end
// Precharge Block - consider NOP if bank already precharged or in process of precharging
if (Prech_enable === 1'b1) begin
// Display Debug Message
if (Debug) begin
$display ("At time %t PRE : Addr[10] = %b, Bank = %b", $time, Addr[10], Ba);
end
 
// LMR/EMR to Precharge
if ($time - MRD_chk < tMRD) begin
$display ("At time %t ERROR: tMRD violation during Precharge", $time);
end
 
// AutoRefresh to Precharge
if ($time - RFC_chk < tRFC) begin
$display ("At time %t ERROR: tRFC violation during Precharge", $time);
end
 
// Precharge bank 0
if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b00)) && Act_b0 === 1'b1) begin
Act_b0 = 1'b0;
Pc_b0 = 1'b1;
RP_chk0 = $time;
// Activate to Precharge Bank
if ($time - RAS_chk0 < tRAS) begin
$display ("At time %t ERROR: tRAS violation during Precharge", $time);
end
// tWR violation check for Write
if ($time - WR_chk0 < tWR) begin
$display ("At time %t ERROR: tWR violation during Precharge", $time);
end
end
 
// Precharge bank 1
if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b01)) && Act_b1 === 1'b1) begin
Act_b1 = 1'b0;
Pc_b1 = 1'b1;
RP_chk1 = $time;
 
// Activate to Precharge Bank 1
if ($time - RAS_chk1 < tRAS) begin
$display ("At time %t ERROR: tRAS violation during Precharge", $time);
end
// tWR violation check for Write
if ($time - WR_chk1 < tWR) begin
$display ("At time %t ERROR: tWR violation during Precharge", $time);
end
end
 
// Precharge bank 2
if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b10)) && Act_b2 === 1'b1) begin
Act_b2 = 1'b0;
Pc_b2 = 1'b1;
RP_chk2 = $time;
// Activate to Precharge Bank 2
if ($time - RAS_chk2 < tRAS) begin
$display ("At time %t ERROR: tRAS violation during Precharge", $time);
end
// tWR violation check for Write
if ($time - WR_chk2 < tWR) begin
$display ("At time %t ERROR: tWR violation during Precharge", $time);
end
end
 
// Precharge bank 3
if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b11)) && Act_b3 === 1'b1) begin
Act_b3 = 1'b0;
Pc_b3 = 1'b1;
RP_chk3 = $time;
// Activate to Precharge Bank 3
if ($time - RAS_chk3 < tRAS) begin
$display ("At time %t ERROR: tRAS violation during Precharge", $time);
end
// tWR violation check for Write
if ($time - WR_chk3 < tWR) begin
$display ("At time %t ERROR: tWR violation during Precharge", $time);
end
end
 
// Prech_count is to make sure we have met part of the initialization sequence
Prech_count = Prech_count + 1;
 
// Pipeline for READ
A10_precharge [cas_latency_x2] = Addr[10];
Bank_precharge[cas_latency_x2] = Ba;
Cmnd_precharge[cas_latency_x2] = 1'b1;
end
// Burst terminate
if (Burst_term === 1'b1) begin
// Display Debug Message
if (Debug) begin
$display ("At time %t BST : Burst Terminate",$time);
end
 
if (Data_in_enable === 1'b1) begin
// Illegal to burst terminate a Write
$display ("At time %t ERROR: It's illegal to burst terminate a Write", $time);
if (!no_halt) $stop (0);
end else if (Read_precharge[0] === 1'b1 || Read_precharge[1] === 1'b1 ||
// Illegal to burst terminate a Read with Auto Precharge
Read_precharge[2] === 1'b1 || Read_precharge[3] === 1'b1) begin
$display ("At time %t ERROR: It's illegal to burst terminate a Read with Auto Precharge", $time);
if (!no_halt) $stop (0);
end else begin
// Burst Terminate Command Pipeline for Read
Cmnd_bst[cas_latency_x2] = 1'b1;
end
 
end
// Read Command
if (Read_enable === 1'b1) begin
if (!(power_up_done)) begin
$display ("%m: at time %t ERROR: Power Up and Initialization Sequence not completed before executing Read Command", $time);
end
// Check for DLL reset before Read
if (DLL_reset === 1 && DLL_done === 0) begin
$display ("%m: at time %t ERROR: You need to wait 200 tCK after DLL Reset Enable to Read, Not %0d clocks.", $time, DLL_count);
end
// Display Debug Message
if (Debug) begin
$display ("At time %t READ : Bank = %h, Col = %h", $time, Ba, {Addr [11], Addr [9 : 0]});
end
 
// Terminate a Write
if (Data_in_enable === 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Activate to Read without Auto Precharge
if ((Addr [10] === 1'b0 && Ba === 2'b00 && $time - RCD_chk0 < tRCD) ||
(Addr [10] === 1'b0 && Ba === 2'b01 && $time - RCD_chk1 < tRCD) ||
(Addr [10] === 1'b0 && Ba === 2'b10 && $time - RCD_chk2 < tRCD) ||
(Addr [10] === 1'b0 && Ba === 2'b11 && $time - RCD_chk3 < tRCD)) begin
$display("At time %t ERROR: tRCD violation during Read", $time);
end
 
// Activate to Read with Auto Precharge
if ((Addr [10] === 1'b1 && Ba === 2'b00 && $time - RAP_chk0 < tRAP) ||
(Addr [10] === 1'b1 && Ba === 2'b01 && $time - RAP_chk1 < tRAP) ||
(Addr [10] === 1'b1 && Ba === 2'b10 && $time - RAP_chk2 < tRAP) ||
(Addr [10] === 1'b1 && Ba === 2'b11 && $time - RAP_chk3 < tRAP)) begin
$display ("At time %t ERROR: tRAP violation during Read", $time);
end
 
// Interrupt a Read with Auto Precharge (same bank only)
if (Read_precharge [Ba] === 1'b1) begin
$display ("At time %t ERROR: It's illegal to interrupt a Read with Auto Precharge", $time);
if (!no_halt) $stop (0);
// Cancel Auto Precharge
if (Addr[10] === 1'b0) begin
Read_precharge [Ba]= 1'b0;
end
end
// Activate to Read
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: Bank is not Activated for Read", $time);
if (!no_halt) $stop (0);
end else begin
// CAS Latency pipeline
Read_cmnd[cas_latency_x2] = 1'b1;
Read_bank[cas_latency_x2] = Ba;
Read_cols[cas_latency_x2] = {Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]};
// Auto Precharge
if (Addr[10] === 1'b1) begin
Read_precharge [Ba]= 1'b1;
Count_precharge [Ba]= 0;
end
end
end
 
// Write Command
if (Write_enable === 1'b1) begin
if (!(power_up_done)) begin
$display ("%m: at time %t ERROR: Power Up and Initialization Sequence not completed before executing Write Command", $time);
if (!no_halt) $stop (0);
end
// display debug message
if (Debug) begin
$display ("At time %t WRITE: Bank = %h, Col = %h", $time, Ba, {Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]});
end
 
// Activate to Write
if ((Ba === 2'b00 && $time - RCD_chk0 < tRCD) ||
(Ba === 2'b01 && $time - RCD_chk1 < tRCD) ||
(Ba === 2'b10 && $time - RCD_chk2 < tRCD) ||
(Ba === 2'b11 && $time - RCD_chk3 < tRCD)) begin
$display("At time %t ERROR: tRCD violation during Write to Bank %h", $time, Ba);
end
 
// Read to Write
if (Read_cmnd[0] || Read_cmnd[1] || Read_cmnd[2] || Read_cmnd[3] ||
Read_cmnd[4] || Read_cmnd[5] || Read_cmnd[6] || (Burst_counter < burst_length)) begin
if (Data_out_enable || read_precharge_truncation[Ba]) begin
$display("At time %t ERROR: Read to Write violation", $time);
end
end
// Interrupt a Write with Auto Precharge (same bank only)
if (Write_precharge [Ba] === 1'b1) begin
$display ("At time %t ERROR: it's illegal to interrupt a Write with Auto Precharge", $time);
if (!no_halt) $stop (0);
// Cancel Auto Precharge
if (Addr[10] === 1'b0) begin
Write_precharge [Ba]= 1'b0;
end
end
// Activate to Write
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: Bank is not Activated for Write", $time);
if (!no_halt) $stop (0);
end else begin
// Pipeline for Write
Write_cmnd [3] = 1'b1;
Write_bank [3] = Ba;
Write_cols [3] = {Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]};
// Auto Precharge
if (Addr[10] === 1'b1) begin
Write_precharge [Ba]= 1'b1;
Count_precharge [Ba]= 0;
end
end
end
end
endtask
 
task check_neg_dqs;
begin
if (Write_cmnd[2] || Write_cmnd[1] || Data_in_enable) begin
for (i=0; i<DQS_BITS; i=i+1) begin
if (expect_neg_dqs[i]) begin
$display ("At time %t ERROR: Negative DQS[%1d] transition required.", $time, i);
end
expect_neg_dqs[i] = 1'b1;
end
end else begin
expect_pos_dqs = 0;
expect_neg_dqs = 0;
end
end
endtask
 
task check_pos_dqs;
begin
if (Write_cmnd[2] || Write_cmnd[1] || Data_in_enable) begin
for (i=0; i<DQS_BITS; i=i+1) begin
if (expect_pos_dqs[i]) begin
$display ("At time %t ERROR: Positive DQS[%1d] transition required.", $time, i);
end
expect_pos_dqs[i] = 1'b1;
end
end else begin
expect_pos_dqs = 0;
expect_neg_dqs = 0;
end
end
endtask
 
// Main Logic
always @ (posedge Sys_clk) begin
Manual_Precharge_Pipeline;
Burst_Terminate_Pipeline;
Dq_Dqs_Drivers;
Write_FIFO_DM_Mask_Logic;
Burst_Decode;
check_neg_dqs;
Auto_Precharge_Calculation;
DLL_Counter;
Control_Logic;
end
 
always @ (negedge Sys_clk) begin
Manual_Precharge_Pipeline;
Burst_Terminate_Pipeline;
Dq_Dqs_Drivers;
Write_FIFO_DM_Mask_Logic;
Burst_Decode;
check_pos_dqs;
end
 
// Dqs Receiver
always @ (posedge Dqs_in[0]) begin
// Latch data at posedge Dqs
dq_rise[7 : 0] = Dq_in[7 : 0];
dm_rise[0] = Dm_in[0];
expect_pos_dqs[0] = 0;
end
 
always @ (posedge Dqs_in[1]) begin
// Latch data at posedge Dqs
dq_rise[15 : 8] = Dq_in[15 : 8];
dm_rise[1] = Dm_in [1];
expect_pos_dqs[1] = 0;
end
 
always @ (negedge Dqs_in[0]) begin
// Latch data at negedge Dqs
dq_fall[7 : 0] = Dq_in[7 : 0];
dm_fall[0] = Dm_in[0];
dm_pair[1:0] = {dm_rise[0], dm_fall[0]};
expect_neg_dqs[0] = 0;
end
 
always @ (negedge Dqs_in[1]) begin
// Latch data at negedge Dqs
dq_fall[15: 8] = Dq_in[15 : 8];
dm_fall[1] = Dm_in[1];
dm_pair[3:2] = {dm_rise[1], dm_fall[1]};
expect_neg_dqs[1] = 0;
end
 
specify
// SYMBOL UNITS DESCRIPTION
// ------ ----- -----------
//`ifdef sg5B // specparams for -5B (CL = 3)
// specparam tDSS = 1.0; // tDSS ns DQS falling edge to CLK rising (setup time) = 0.2*tCK
// specparam tDSH = 1.0; // tDSH ns DQS falling edge from CLK rising (hold time) = 0.2*tCK
// specparam tIH = 0.600; // tIH ns Input Hold Time
// specparam tIS = 0.600; // tIS ns Input Setup Time
// specparam tDQSH = 1.75; // tDQSH ns DQS input High Pulse Width = 0.35*tCK
// specparam tDQSL = 1.75; // tDQSL ns DQS input Low Pulse Width = 0.35*tCK
//`else `ifdef sg6 // specparams for -6 (CL = 2.5)
specparam tDSS = 1.2; // tDSS ns DQS falling edge to CLK rising (setup time) = 0.2*tCK
specparam tDSH = 1.2; // tDSH ns DQS falling edge from CLK rising (hold time) = 0.2*tCK
specparam tIH = 0.750; // tIH ns Input Hold Time
specparam tIS = 0.750; // tIS ns Input Setup Time
specparam tDQSH = 2.1; // tDQSH ns DQS input High Pulse Width = 0.35*tCK
specparam tDQSL = 2.1; // tDQSL ns DQS input Low Pulse Width = 0.35*tCK
//`else `ifdef sg75E // specparams for -75E (CL = 2)
// specparam tDSS = 1.5; // tDSS ns DQS falling edge to CLK rising (setup time) = 0.2*tCK
// specparam tDSH = 1.5; // tDSH ns DQS falling edge from CLK rising (hold time) = 0.2*tCK
// specparam tIH = 0.900; // tIH ns Input Hold Time
// specparam tIS = 0.900; // tIS ns Input Setup Time
// specparam tDQSH = 2.625; // tDQSH ns DQS input High Pulse Width = 0.35*tCK
// specparam tDQSL = 2.625; // tDQSL ns DQS input Low Pulse Width = 0.35*tCK
//`else
//`define sg75Z // specparams for -75Z (CL = 2)
// specparam tDSS = 1.5; // tDSS ns DQS falling edge to CLK rising (setup time) = 0.2*tCK
// specparam tDSH = 1.5; // tDSH ns DQS falling edge from CLK rising (hold time) = 0.2*tCK
// specparam tIH = 0.900; // tIH ns Input Hold Time
// specparam tIS = 0.900; // tIS ns Input Setup Time
// specparam tDQSH = 2.625; // tDQSH ns DQS input High Pulse Width = 0.35*tCK
// specparam tDQSL = 2.625; // tDQSL ns DQS input Low Pulse Width = 0.35*tCK
//`endif `endif `endif
$width (posedge Dqs_in[0] &&& wdqs_valid, tDQSH);
$width (posedge Dqs_in[1] &&& wdqs_valid, tDQSH);
$width (negedge Dqs_in[0] &&& wdqs_valid, tDQSL);
$width (negedge Dqs_in[1] &&& wdqs_valid, tDQSL);
$setuphold(posedge Clk, Cke, tIS, tIH);
$setuphold(posedge Clk, Cs_n, tIS, tIH);
$setuphold(posedge Clk, Cas_n, tIS, tIH);
$setuphold(posedge Clk, Ras_n, tIS, tIH);
$setuphold(posedge Clk, We_n, tIS, tIH);
$setuphold(posedge Clk, Addr, tIS, tIH);
$setuphold(posedge Clk, Ba, tIS, tIH);
$setuphold(posedge Clk, negedge Dqs &&& wdqs_valid, tDSS, tDSH);
endspecify
 
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.