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 |