--- /unisims/OSERDESE1.v 1969-12-31 17:00:00.000000000 -0700 +++ ../../vdt-projects/eddr3/unisims/OSERDESE1.v 2014-05-21 09:38:37.691045918 -0600 @@ -0,0 +1,3293 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 1995/2005 Xilinx, Inc. +// All Right Reserved. +/////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor : Xilinx +// \ \ \/ Version : 10.1 +// \ \ Description : Xilinx Timing Simulation Library Component +// / / Source Synchronous Output Serializer +// /___/ /\ Filename : OSERDESE1.v +// \ \ / \ Timestamp : Tue Sep 16 15:30:44 PDT 2008 +// \___\/\___\ +// +// Revision: +// 09/16/08 - Initial version. +// 12/05/08 - IR 495397. +// 01/13/09 - IR 503429. +// 01/15/09 - IR 503783 CLKPERF is not inverted for OFB/ofb_out. +// 02/06/09 - CR 507373 Removed IOCLKGLITCH and CLKB +// 02/26/09 - CR 510489 fixed SHIFTIN2_in +// 03/16/09 - CR 512140 and 512139 -- sdf load errors +// 01/27/10 - CR 546419 Updated specify block +// 12/13/11 - Added `celldefine and `endcelldefine (CR 524859). +// 09/04/12 - 676501 CLK -> OFB specify path missing +// End Revision + +`timescale 1 ps / 1 ps +`celldefine + +module OSERDESE1 (OCBEXTEND, OFB, OQ, SHIFTOUT1, SHIFTOUT2, TFB, TQ, + CLK, CLKDIV, CLKPERF, CLKPERFDELAY, D1, D2, D3, D4, D5, D6, OCE, ODV, RST, SHIFTIN1, SHIFTIN2, T1, T2, T3, T4, TCE, WC); + + + parameter DATA_RATE_OQ = "DDR"; + parameter DATA_RATE_TQ = "DDR"; + parameter integer DATA_WIDTH = 4; + parameter integer DDR3_DATA = 1; + parameter [0:0] INIT_OQ = 1'b0; + parameter [0:0] INIT_TQ = 1'b0; + parameter INTERFACE_TYPE = "DEFAULT"; + parameter integer ODELAY_USED = 0; + parameter SERDES_MODE = "MASTER"; + parameter [0:0] SRVAL_OQ = 1'b0; + parameter [0:0] SRVAL_TQ = 1'b0; + parameter integer TRISTATE_WIDTH = 4; + + + `ifdef XIL_TIMING + parameter LOC = "UNPLACED"; + `endif + +//------------------------------------------------------------- +// Outputs: +//------------------------------------------------------------- +// OQ: Data output +// TQ: Output of tristate mux +// SHIFTOUT1: Carry out data 1 for slave +// SHIFTOUT2: Carry out data 2 for slave +// OFB: O Feedback output + +// +//------------------------------------------------------------- +// Inputs: +//------------------------------------------------------------- +// +// Inputs: +// CLK: High speed clock from DCM +// CLKB: Inverted High speed clock from DCM +// CLKDIV: Low speed divided clock from DCM +// CLKPERF: Performance Path clock +// CLKPERFDELAY: delayed Performance Path clock +// D1, D2, D3, D4, D5, D6 : Data inputs +// OCE: Clock enable for output data flops +// ODV: ODELAY value > 140 degrees +// RST: Reset control +// T1, T2, T3, T4: tristate inputs +// SHIFTIN1: Carry in data 1 for master from slave +// SHIFTIN2: Carry in data 2 for master from slave +// TCE: Tristate clock enable +// WC: Write command given by memory controller + + output OCBEXTEND; + output OFB; + output OQ; + output SHIFTOUT1; + output SHIFTOUT2; + output TFB; + output TQ; + + input CLK; + input CLKDIV; + input CLKPERF; + input CLKPERFDELAY; + input D1; + input D2; + input D3; + input D4; + input D5; + input D6; + input OCE; + input ODV; + input RST; + input SHIFTIN1; + input SHIFTIN2; + input T1; + input T2; + input T3; + input T4; + input TCE; + input WC; + + +// + wire SERDES, DDR_CLK_EDGE; + wire [5:0] SRTYPE; + wire WC_DELAY; + wire [4:0] SELFHEAL; + + + wire load; + wire qmux1, qmux, tmux1, tmux2; + wire data1, data2, triin1, triin2; + wire d2rnk2; + wire CLKD; + wire CLKDIVD; + wire iodelay_state; + +// attribute + reg data_rate_int; + reg [3:0] data_width_int; + reg [1:0] tristate_width_int; + reg data_rate_oq_int; + reg [1:0] data_rate_tq_int; + reg ddr3_data_int; + reg interface_type_int; + reg odelay_used_int; + reg serdes_mode_int; + +// Output signals + wire ioclkglitch_out, ocbextend_out, ofb_out, oq_out, tq_out, shiftout1_out, shiftout2_out; + +// Other signals + tri0 GSR = glbl.GSR; + + reg notifier; + + wire CLK_in; + wire CLKDIV_in; + wire CLKPERF_in; + wire CLKPERFDELAY_in; + wire D1_in; + wire D2_in; + wire D3_in; + wire D4_in; + wire D5_in; + wire D6_in; + wire OCE_in; + wire ODV_in; + wire RST_in; + wire SHIFTIN1_in; + wire SHIFTIN2_in; + wire T1_in; + wire T2_in; + wire T3_in; + wire T4_in; + wire TCE_in; + wire WC_in; + +`ifndef XIL_TIMING + + assign CLK_in = CLK; + assign CLKDIV_in = CLKDIV; + assign D1_in = D1; + assign D2_in = D2; + assign D3_in = D3; + assign D4_in = D4; + assign D5_in = D5; + assign D6_in = D6; + assign OCE_in = OCE; + assign T1_in = T1; + assign T2_in = T2; + assign T3_in = T3; + assign T4_in = T4; + assign TCE_in = TCE; + assign WC_in = WC; + +`endif // `ifndef XIL_TIMING + + + assign CLKPERF_in = CLKPERF; +// assign CLKPERFDELAY_in = CLKPERFDELAY; +// IR 495397 & IR 499954 +// assign CLKPERFDELAY_in = (CLKPERFDELAY === 1'bx)? 1'b0 : CLKPERFDELAY; + generate + case (ODELAY_USED) + 0: assign CLKPERFDELAY_in = CLKPERF; + 1: assign CLKPERFDELAY_in = (CLKPERFDELAY === 1'bx)? 1'b0 : CLKPERFDELAY; + endcase + endgenerate + + assign SHIFTIN1_in = SHIFTIN1; + assign SHIFTIN2_in = SHIFTIN2; + assign ODV_in = ODV; + assign RST_in = RST; + + buf b_ocbextend (OCBEXTEND, ocbextend_out); + buf b_ofb (OFB, ofb_out); + buf b_oq (OQ, oq_out); + buf b_shiftout1 (SHIFTOUT1, shiftout1_out); + buf b_shiftout2 (SHIFTOUT2, shiftout2_out); + buf b_tfb (TFB, tfb_out); + buf b_tq (TQ, tq_out); + + + initial begin + +//------------------------------------------------- +//----- DATA_RATE_OQ check +//------------------------------------------------- + case (DATA_RATE_OQ) + "SDR" : data_rate_oq_int <= 1'b1; + "DDR" : data_rate_oq_int <= 1'b0; + default : begin + $display("Attribute Syntax Error : The attribute DATA_RATE_OQ on OSERDESE1 instance %m is set to %s. Legal values for this attribute are SDR or DDR", DATA_RATE_OQ); + $display("finish OSERDESE1 1"); + $finish; + end + endcase // case(DATA_RATE_OQ) + +//------------------------------------------------- +//----- DATA_RATE_TQ check +//------------------------------------------------- + case (DATA_RATE_TQ) + + "BUF" : data_rate_tq_int <= 2'b00; + "SDR" : data_rate_tq_int <= 2'b01; + "DDR" : data_rate_tq_int <= 2'b10; + default : begin + $display("Attribute Syntax Error : The attribute DATA_RATE_TQ on OSERDESE1 instance %m is set to %s. Legal values for this attribute are BUF, SDR or DDR", DATA_RATE_TQ); + $display("finish OSERDESE1 2"); + $finish; + end + + endcase // case(DATA_RATE_TQ) + +//------------------------------------------------- +//----- DATA_WIDTH check +//------------------------------------------------- + case (DATA_WIDTH) + + 2, 3, 4, 5, 6, 7, 8, 10 : data_width_int = DATA_WIDTH; + default : begin + $display("Attribute Syntax Error : The attribute DATA_WIDTH on OSERDESE1 instance %m is set to %d. Legal values for this attribute are 2, 3, 4, 5, 6, 7, 8, or 10", DATA_WIDTH); + $display("finish OSERDESE1 3"); + $finish; + end + endcase // case(DATA_WIDTH) + +//------------------------------------------------- +//----- DDR3_DATA check +//------------------------------------------------- + case (DDR3_DATA) + 0 : ddr3_data_int <= 1'b0; + 1 : ddr3_data_int <= 1'b1; + default : begin + $display("Attribute Syntax Error : The attribute DDR3_DATA on OSERDESE1 instance %m is set to %d. Legal values for this attribute are 0 or 1", DDR3_DATA); + $display("finish OSERDESE1 4"); + $finish; + end + endcase // case(DDR3_DATA) + +//------------------------------------------------- +//----- INTERFACE_TYPE check +//------------------------------------------------- + case (INTERFACE_TYPE) + "DEFAULT" : interface_type_int <= 1'b0; + "MEMORY_DDR3" : interface_type_int <= 1'b1; + default : begin + $display("Attribute Syntax Error : The attribute INTERFACE_TYPE on OSERDESE1 instance %m is set to %s. Legal values for this attribute are DEFAULT, or MEMORY_DDR3", INTERFACE_TYPE); + $display("finish OSERDESE1 5"); + $finish; + end + endcase // INTERFACE_TYPE + + +//------------------------------------------------- +//----- ODELAY_USED check +//------------------------------------------------- + case (ODELAY_USED) + +// "FALSE" : odelay_used_int <= 1'b0; +// "TRUE" : odelay_used_int <= 1'b1; + 0 : odelay_used_int <= 1'b0; + 1 : odelay_used_int <= 1'b1; + default : begin + $display("Attribute Syntax Error : The attribute ODELAY_USED on OSERDESE1 instance %m is set to %s. Legal values for this attribute are FALSE or TRUE", ODELAY_USED); + $display("finish OSERDESE1 6"); + $finish; + end + + endcase // case(ODELAY_USED) + +//------------------------------------------------- +//----- SERDES_MODE check +//------------------------------------------------- + case (SERDES_MODE) + + "MASTER" : serdes_mode_int <= 1'b0; + "SLAVE" : serdes_mode_int <= 1'b1; + default : begin + $display("Attribute Syntax Error : The attribute SERDES_MODE on OSERDESE1 instance %m is set to %s. Legal values for this attribute are MASTER or SLAVE", SERDES_MODE); + $display("finish OSERDESE1 7"); + $finish; + end + + endcase // case(SERDES_MODE) + +//------------------------------------------------- +//----- TRISTATE_WIDTH check +//------------------------------------------------- + case (TRISTATE_WIDTH) + + 1 : tristate_width_int <= 2'b00; + 2 : tristate_width_int <= 2'b01; + 4 : tristate_width_int <= 2'b10; + default : begin + $display("Attribute Syntax Error : The attribute TRISTATE_WIDTH on OSERDESE1 instance %m is set to %d. Legal values for this attribute are 1, 2 or 4", TRISTATE_WIDTH); + $display("finish OSERDESE1 8"); + $finish; + end + + endcase // case(TRISTATE_WIDTH) +// $display("Info: The attribute TRISTATE_WIDTH on OSERDESE1 instance %m is set to %d", TRISTATE_WIDTH); + +//------------------------------------------------- + end // initial begin + +//------------------------------------------------- + + assign SERDES = 1'b1; + assign SRTYPE = 6'b111111; + assign DDR_CLK_EDGE = 1'b1; + assign WC_DELAY = 1'b0; + assign SELFHEAL = 5'b00000; + + assign #0 CLKD = CLK; + assign #0 CLKDIVD = CLKDIV; + + + assign #10 ofb_out = (ODELAY_USED == 1)? CLKPERF : oq_out; + assign #10 tfb_out = iodelay_state; + + +///////////////////////////////////////////////////////// +// +// Delay assignments +// +///////////////////////////////////////////////////////// + +// Data output delays +defparam dfront.FFD = 1; // clock to out delay for flip flops +// driven by clk +defparam datao.FFD = 1; // clock to out delay for flip flops +// driven by clk +defparam dfront.FFCD = 1; // clock to out delay for flip flops +// driven by clkdiv +defparam dfront.MXD = 1; // mux delay + +defparam dfront.MXR1 = 1; // mux before 2nd rank of flops + +// Programmable load generator +defparam dfront.ldgen.ffdcnt = 1; +defparam dfront.ldgen.mxdcnt = 1; +defparam dfront.ldgen.FFRST = 145; // clock to out delay for flop in PLSG + +// Tristate output delays +defparam tfront.ffd = 1; // clock to out delay for flip flops +defparam tfront.mxd = 1; // mux delay + +defparam trio.ffd = 1; // clock to out delay for flip flops +defparam trio.mxd = 1; // mux delay + +//------------------------------------------------------------------ +// Instantiate output data section +//------------------------------------------------------------------ + +rank12d_oserdese1_vlog dfront (.D1(D1_in), .D2(D2_in), .D3(D3_in), .D4(D4_in), .D5(D5_in), .D6(D6_in), + .d2rnk2(d2rnk2), + .SHIFTIN1(SHIFTIN1_in), .SHIFTIN2(SHIFTIN2_in), + .C(CLK_in), .CLKDIV(CLKDIV_in), .SR(RST_in), .OCE(OCE_in), + .data1(data1), .data2(data2), .SHIFTOUT1(shiftout1_out), .SHIFTOUT2(shiftout2_out), + .DATA_RATE_OQ(data_rate_oq_int), .DATA_WIDTH(data_width_int), + .SERDES_MODE(serdes_mode_int), .load(load), + .IOCLK_GLITCH(ioclkglitch_out), + .INIT_OQ(INIT_OQ), .SRVAL_OQ(SRVAL_OQ)); + + +trif_oserdese1_vlog tfront (.T1(T1_in), .T2(T2_in), .T3(T3_in), .T4(T4_in), .load(load), + .C(CLK_in), .CLKDIV(CLKDIV_in), .SR(RST_in), .TCE(TCE_in), + .DATA_RATE_TQ(data_rate_tq_int), .TRISTATE_WIDTH(tristate_width_int), + .INIT_TQ(INIT_TQ), .SRVAL_TQ(SRVAL_TQ), + .data1(triin1), .data2(triin2)); + + +txbuffer_oserdese1_vlog DDR3FIFO (.iodelay_state(iodelay_state), .qmux1(qmux1), .qmux2(qmux2), .tmux1(tmux1), .tmux2(tmux2), + .d1(data1), .d2(data2), .t1(triin1), .t2(triin2), .trif(tq_out), + .WC(WC_in), .ODV(ODV_in), .extra(ocbextend_out), + .clk(CLK_in), .clkdiv(CLKDIV_in), .bufo(CLKPERFDELAY_in), .bufop(CLKPERF_in), .rst(RST_in), + .ODELAY_USED(odelay_used_int), .DDR3_DATA(ddr3_data_int), + .DDR3_MODE(interface_type_int)); + +dout_oserdese1_vlog datao (.data1(qmux1), .data2(qmux2), + .CLK(CLK_in), .BUFO(CLKPERFDELAY_in), .SR(RST_in), .OCE(OCE_in), + .OQ(oq_out), .d2rnk2(d2rnk2), + .DATA_RATE_OQ(data_rate_oq_int), + .INIT_OQ(INIT_OQ), .SRVAL_OQ(SRVAL_OQ), + .DDR3_MODE(interface_type_int)); + +tout_oserdese1_vlog trio (.data1(tmux1), .data2(tmux2), + .CLK(CLK_in), .BUFO(CLKPERFDELAY_in), .SR(RST_in), .TCE(TCE_in), + .DATA_RATE_TQ(data_rate_tq_int), .TRISTATE_WIDTH(tristate_width_int), + .INIT_TQ(INIT_TQ), .SRVAL_TQ(SRVAL_TQ), + .TQ(tq_out), .DDR3_MODE(interface_type_int)); + + +`ifndef XIL_TIMING + specify + ( CLK => OFB) = (100, 100); + ( CLK => OQ) = (100, 100); + ( CLK => TQ) = (100, 100); + ( CLKPERF => OQ) = (100, 100); + ( CLKPERF => TQ) = (100, 100); + ( CLKPERFDELAY => OQ) = (100, 100); + ( CLKPERFDELAY => TQ) = (100, 100); + ( T1 => TQ) = (0, 0); + + specparam PATHPULSE$ = 0; + + endspecify +`endif // `ifndef XIL_TIMING + +`ifdef XIL_TIMING +//*** Timing Checks Start here + + specify + ( CLK => OFB) = (100:100:100, 100:100:100); + ( CLK => OQ) = (100:100:100, 100:100:100); + ( CLK => TQ) = (100:100:100, 100:100:100); + ( CLKPERF => OQ) = (100:100:100, 100:100:100); + ( CLKPERF => TQ) = (100:100:100, 100:100:100); + ( CLKPERFDELAY => OQ) = (100:100:100, 100:100:100); + ( CLKPERFDELAY => TQ) = (100:100:100, 100:100:100); + ( T1 => TQ) = (0:0:0, 0:0:0); + + $setuphold (posedge CLK, negedge OCE, 0:0:0, 0:0:0, notifier,,, CLK_in, OCE_in); + $setuphold (posedge CLK, negedge T1, 0:0:0, 0:0:0, notifier,,, CLK_in, T1_in); + $setuphold (posedge CLK, negedge TCE, 0:0:0, 0:0:0, notifier,,, CLK_in, TCE_in); + $setuphold (posedge CLK, posedge OCE, 0:0:0, 0:0:0, notifier,,, CLK_in, OCE_in); + $setuphold (posedge CLK, posedge T1, 0:0:0, 0:0:0, notifier,,, CLK_in, T1_in); + $setuphold (posedge CLK, posedge TCE, 0:0:0, 0:0:0, notifier,,, CLK_in, TCE_in); + $setuphold (posedge CLKDIV, negedge D1, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D1_in); + $setuphold (posedge CLKDIV, negedge D2, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D2_in); + $setuphold (posedge CLKDIV, negedge D3, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D3_in); + $setuphold (posedge CLKDIV, negedge D4, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D4_in); + $setuphold (posedge CLKDIV, negedge D5, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D5_in); + $setuphold (posedge CLKDIV, negedge D6, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D6_in); + $setuphold (posedge CLKDIV, negedge RST, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, RST_in); + $setuphold (posedge CLKDIV, negedge T1, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T1_in); + $setuphold (posedge CLKDIV, negedge T2, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T2_in); + $setuphold (posedge CLKDIV, negedge T3, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T3_in); + $setuphold (posedge CLKDIV, negedge T4, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T4_in); + $setuphold (posedge CLKDIV, negedge WC, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, WC_in); + $setuphold (posedge CLKDIV, posedge D1, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D1_in); + $setuphold (posedge CLKDIV, posedge D2, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D2_in); + $setuphold (posedge CLKDIV, posedge D3, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D3_in); + $setuphold (posedge CLKDIV, posedge D4, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D4_in); + $setuphold (posedge CLKDIV, posedge D5, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D5_in); + $setuphold (posedge CLKDIV, posedge D6, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D6_in); + $setuphold (posedge CLKDIV, posedge RST, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, RST_in); + $setuphold (posedge CLKDIV, posedge T1, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T1_in); + $setuphold (posedge CLKDIV, posedge T2, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T2_in); + $setuphold (posedge CLKDIV, posedge T3, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T3_in); + $setuphold (posedge CLKDIV, posedge T4, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T4_in); + $setuphold (posedge CLKDIV, posedge WC, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, WC_in); + + specparam PATHPULSE$ = 0; + + endspecify +`endif // `ifdef XIL_TIMING + + +endmodule // OSERDESE1 + +`timescale 1ps/1ps +///////////////////////////////////////////////////////// +// +// module selfheal_oserdese1_vlog +// +/////////////////////////////////////////////////////// +// +// Self healing circuit for Mt Blanc +// This model ONLY works for SERDES operation!! +// +// +// +//////////////////////////////////////////////////////// +// +// +// +///////////////////////////////////////////////////////// +// +// Inputs: +// dq3 - dq0: Data from load counter +// CLKDIV: Divided clock from PLL +// srint: RESET from load generator +// rst: Set/Reset control +// +// +// +// Outputs: +// SHO: Data output +// +// +// +// Programmable Points +// SELFHEAL: String of 5 bits. 1 as enable and 4 as compare +// Test attributes in model +// +// +// +// +// +//////////////////////////////////////////////////////////////////////////////// +// + +module selfheal_oserdese1_vlog (dq3, dq2, dq1, dq0, + CLKDIV, srint, rst, + SHO); + +input dq3, dq2, dq1, dq0; + +input CLKDIV, srint, rst; + +output SHO; + + +reg shr; + +reg SHO; + + +wire clkint; + +wire error; + +wire rst_in, rst_self_heal; + + +// Programmable Points + +wire [4:0] SELFHEAL; +assign SELFHEAL = 5'b00000; + + + +////////////////////////////////////////////////// +// Delay values +// +parameter FFD = 10; // clock to out delay for flip flops +// driven by clk +parameter FFCD = 10; // clock to out delay for flip flops +// driven by clkdiv +parameter MXD = 10; // 60 ps mux delay + +parameter MXR1 = 10; + + + +///////////////////////////////////////// + + +assign clkint = CLKDIV & SELFHEAL[4]; + +assign error = (((~SELFHEAL[4] ^ SELFHEAL[3]) ^ dq3) | ((~SELFHEAL[4] ^ SELFHEAL[2]) ^ dq2) | ((~SELFHEAL[4] ^ SELFHEAL[1]) ^ dq1) | ((~SELFHEAL[4] ^ SELFHEAL[0]) ^ dq0)); + +assign rst_in = (~SELFHEAL[4] | ~srint); + +assign rst_self_heal = (rst | ~shr); + +///////////////////////////////////////// +// Reset Flop +//////////////////////////////////////// + +always @ (posedge clkint or posedge rst) +begin + begin + if (rst) + begin + shr <= # FFD 1'b0; + end + else begin + shr <= #FFD rst_in; + end + end +end + +// Self heal flop +always @ (posedge clkint or posedge rst_self_heal) +begin + begin + + if (rst_self_heal) + begin + SHO <= 1'b0; + end + else + begin + SHO <= # FFD error; + end + end +end + + + + +endmodule +`timescale 1ps/1ps +//////////////////////////////////////////////////////// +// +// module plg_oserdese1_vlog +// +//////////////////////////////////////////////////////// +// +// Programmable Load Generator (PLG) +// Divide by 2-8 counter with load enable output +// +// +///////////////////////////////////////////////////////// +// +// Inputs: +// c23: Selects between divide by 2 or 3 +// c45: Selects between divide by 4 or 5 +// c67: Selects between divide by 6 or 7 +// sel: Selects which divide function is chosen +// 00:2 or 3, 01:4 or 5, 10:6 or 7, 11:8 +// clk: High speed clock from DCM +// clkdiv: Low speed clock from DCM +// rst: Reset +// +// +// +// Outputs: +// +// load: Loads serdes register at terminal count +// +// +// Test attributes: +// INIT_LOADCNT: 4-bits to init counter +// SRTYPE: 1-bit to control synchronous or asynchronous operation +// SELFHEAL: 5-bits to control self healing feature +// +// +// +//////////////////////////////////////////////////////////////////////////////// +// + +module plg_oserdese1_vlog (c23, c45, c67, sel, + clk, clkdiv, rst, + load, IOCLK_GLITCH); + +input c23, c45, c67; + +input [1:0] sel; + +input clk, clkdiv, rst; + +output load; + +output IOCLK_GLITCH; + +wire SRTYPE; +wire [3:0] INIT_LOADCNT; +wire [4:0] SELFHEAL; +assign SRTYPE = 1'b1; +assign INIT_LOADCNT = 4'b0000; +assign SELFHEAL = 5'b00000; + +reg q0, q1, q2, q3; + +reg qhr, qlr; + +reg load, mux; + +wire cntrrst; + + +assign cntrrst = IOCLK_GLITCH | rst; + + + +// Parameters for gate delays +parameter ffdcnt = 1; +parameter mxdcnt = 1; +parameter FFRST = 145; // clock to out delay for flop in PLSG + + + +////////////////////////////////////////////////// + +tri0 GSR = glbl.GSR; + +always @(GSR) +begin + if (GSR) + begin + force q3 = INIT_LOADCNT[3]; + force q2 = INIT_LOADCNT[2]; + force q1 = INIT_LOADCNT[1]; + force q0 = INIT_LOADCNT[0]; + end + else + begin + release q3; + release q2; + release q1; + release q0; + end +end + + + + + + + +// flops for counter +// asynchronous reset +always @ (posedge qhr or posedge clk) +begin + if (qhr & !SRTYPE) + begin + q0 <= # ffdcnt 1'b0; + q1 <= # ffdcnt 1'b0; + q2 <= # ffdcnt 1'b0; + q3 <= # ffdcnt 1'b0; + end + else if (!SRTYPE) + begin + q3 <= # ffdcnt q2; + q2 <= # ffdcnt (!(!q0 & !q2) & q1); + q1 <= # ffdcnt q0; + q0 <= # ffdcnt mux; + end +end +// synchronous reset +always @ (posedge clk) +begin + if (qhr & SRTYPE) + begin + q0 <= # ffdcnt 1'b0; + q1 <= # ffdcnt 1'b0; + q2 <= # ffdcnt 1'b0; + q3 <= # ffdcnt 1'b0; + end + else if (SRTYPE) + begin + q3 <= # ffdcnt q2; + q2 <= # ffdcnt (!(!q0 & !q2) & q1); + q1 <= # ffdcnt q0; + q0 <= # ffdcnt mux; + end +end + + +// mux settings for counter +always @ (sel or c23 or c45 or c67 or q0 or q1 or q2 or q3) + begin + case (sel) + 2'b00: mux <= # mxdcnt (!q0 & !(c23 & q1)); + 2'b01: mux <= # mxdcnt (!q1 & !(c45 & q2)); + 2'b10: mux <= # mxdcnt (!q2 & !(c67 & q3)); + 2'b11: mux <= # mxdcnt !q3; + default: mux <= # mxdcnt 1'b0; + endcase + end + + +// mux decoding for load signal +always @ (sel or c23 or c45 or c67 or q0 or q1 or q2 or q3) + begin + case (sel) + 2'b00: load <= # mxdcnt q0; + 2'b01: load <= # mxdcnt q0 & q1; + 2'b10: load <= # mxdcnt q0 & q2; + 2'b11: load <= # mxdcnt q0 & q3; + default: load <= # mxdcnt 1'b0; + endcase + end + +// flops to reset counter + +// Low speed flop +// asynchronous reset +always @ (posedge cntrrst or posedge clkdiv) + begin + if (cntrrst & !SRTYPE) + begin + qlr <= # FFRST 1'b1; + end + else if (!SRTYPE) + begin + qlr <= # FFRST 1'b0; + end + end +// synchronous reset +always @ (posedge clkdiv) + begin + if (cntrrst & SRTYPE) + begin + qlr <= # FFRST 1'b1; + end + else if (SRTYPE) + begin + qlr <= # FFRST 1'b0; + end + end + + + +// High speed flop +// asynchronous reset +always @ (posedge cntrrst or posedge clk) + begin + if (cntrrst & !SRTYPE) + begin + qhr <= # ffdcnt 1'b1; + end + else if (!SRTYPE) + begin + qhr <= # ffdcnt qlr; + end + end +// synchronous reset +always @ (posedge clk) + begin + if (cntrrst & SRTYPE) + begin + qhr <= # ffdcnt 1'b1; + end + else if (SRTYPE) + begin + qhr <= # ffdcnt qlr; + end + end + +selfheal_oserdese1_vlog fixcntr (.dq3(q3), .dq2(q2), .dq1(q1), .dq0(q0), + .CLKDIV(clkdiv), .srint(qlr), .rst(rst), + .SHO(IOCLK_GLITCH)); +endmodule +`timescale 1ps/1ps +//////////////////////////////////////////////////////// +// +// module rank12d_oserdese1_vlog +// +// +// This model ONLY works for SERDES operation!! +// Does not include tristate circuit +// +// +//////////////////////////////////////////////////////// +// +// Inputs: +// D1: Data input 1 +// D2: Data input 2 +// D3: Data input 3 +// D4: Data input 4 +// D5: Data input 5 +// D6: Data input 6 +// C: High speed clock from DCM +// OCE: Clock enable for output data flops +// SR: Set/Reset control. For the last 3 flops in OQ +// (d1rnk2, d2rnk2 and d2nrnk2) this function is +// controlled bythe attributes SRVAL_OQ. In SERDES mode, +// SR is a RESET ONLY for all other flops! The flops will +// still be RESET even if SR is programmed to a SET! +// CLKDIV: Low speed divided clock from DCM +// SHIFTIN1: Carry in data 1 for master from slave +// SHIFTIN2: Carry in data 2 for master from slave +// +// +// +// Outputs: +// data1: Data output mux for top flop +// data2: Data output mux for bottom flop +// SHIFTOUT1: Carry out data 1 for slave +// SHIFTOUT2: Carry out data 2 for slave +// load: Used for the tristate when combined into a single model +// +// +// +// Programmable Points +// DATA_RATE_OQ: Rate control for data output, 1-bit +// sdr (1), ddr (0) +// DATA_WIDTH: Input data width, +// 4-bits, values can be from 2 to 10 +// SERDES_MODE: Denotes master (0) or slave (1) +// SIM_X_INPUT: This attribute is NOT SUPPORTED in this model!!! +// +// +// +// Programmable points for Test model +// SRTYPE: This is a 4-bit field Sets asynchronous (0) or synchronous (1) set/reset +// 1st bit (msb) sets rank1 flops, 2nd bit sets 4 flops in rank 2, +// 3rd bit sets "3 legacy flops, and 4th (lsb) bit sets the counter +// INIT_ORANK1: Init value for 6 registers in 1st rank (6-bits) +// INIT_ORANK2_PARTIAL: Init value for bottom 4 registers in the 2nd rank (4-bits) +// INIT_LOADCNT: Init value for the load counter (4-bits) +// The other 2 registers in the load counter have init bits, but are +// not supported in this model +// SERDES: Indicates that SERDES mode is chosen +// SLEFHEAL: 5-bit to set self heal circuit +// +// +//////////////////////////////////////////////////////////////////////////////// +// + +module rank12d_oserdese1_vlog (D1, D2, D3, D4, D5, D6, d2rnk2, + SHIFTIN1, SHIFTIN2, + C, CLKDIV, SR, OCE, + data1, data2, SHIFTOUT1, SHIFTOUT2, + DATA_RATE_OQ, DATA_WIDTH, + SERDES_MODE, load, + IOCLK_GLITCH, + INIT_OQ, SRVAL_OQ); + +input D1, D2, D3, D4, D5, D6; + +input d2rnk2; + +input SHIFTIN1, SHIFTIN2; + +input C, CLKDIV, SR, OCE; + +input INIT_OQ, SRVAL_OQ; + +output data1, data2; + +output SHIFTOUT1, SHIFTOUT2; + +output load; + +output IOCLK_GLITCH; + +// Programmable Points + +input DATA_RATE_OQ; + +input [3:0] DATA_WIDTH; + +input SERDES_MODE; + +wire DDR_CLK_EDGE, SERDES; +wire [3:0] SRTYPE; +wire [4:0] SELFHEAL; + +wire [3:0] INIT_ORANK2_PARTIAL; +wire [5:0] INIT_ORANK1; + +assign DDR_CLK_EDGE = 1'b1; +assign SERDES = 1'b1; +assign SRTYPE = 4'b1111; +assign SELFHEAL = 5'b00000; + +assign INIT_ORANK2_PARTIAL = 4'b0000; +assign INIT_ORANK1 = 6'b000000; + +reg d1r, d2r, d3r, d4r, d5r, d6r; + +reg d3rnk2, d4rnk2, d5rnk2, d6rnk2; + +reg data1, data2, data3, data4, data5, data6; + +reg ddr_data, odata_edge, sdata_edge; + +reg c23, c45, c67; + +reg [1:0] sel; + +wire C2p, C3; + +wire loadint; + +wire [3:0] seloq; + +wire oqsr, oqrev; + +wire [2:0] sel1_4; + +wire [3:0] sel5_6; + +wire [4:0] plgcnt; + +assign C2p = (C & DDR_CLK_EDGE) | (!C & !DDR_CLK_EDGE); + +assign C3 = !C2p; + +assign plgcnt = {DATA_RATE_OQ,DATA_WIDTH}; + +assign sel1_4 = {SERDES,loadint,DATA_RATE_OQ}; + +assign sel5_6 = {SERDES,SERDES_MODE,loadint,DATA_RATE_OQ}; + +assign load = loadint; + +assign seloq = {OCE,DATA_RATE_OQ,oqsr,oqrev}; + +assign oqsr = !SRTYPE[1] & SR & !SRVAL_OQ; + +assign oqrev = !SRTYPE[1] & SR & SRVAL_OQ; + + + +////////////////////////////////////////////////// +// Delay values +// +parameter FFD = 1; // clock to out delay for flip flops +// driven by clk +parameter FFCD = 1; // clock to out delay for flip flops +// driven by clkdiv +parameter MXD = 1; // 60 ps mux delay + +parameter MXR1 = 1; + +//////////////////////////////////////////// +// Initialization of flops with GSR for test model +/////////////////////////////////////////// + +tri0 GSR = glbl.GSR; + +always @(GSR) +begin + if (GSR) + begin + force d6rnk2 = INIT_ORANK2_PARTIAL[3]; + force d5rnk2 = INIT_ORANK2_PARTIAL[2]; + force d4rnk2 = INIT_ORANK2_PARTIAL[1]; + force d3rnk2 = INIT_ORANK2_PARTIAL[0]; + + force d6r = INIT_ORANK1[5]; + force d5r = INIT_ORANK1[4]; + force d4r = INIT_ORANK1[3]; + force d3r = INIT_ORANK1[2]; + force d2r = INIT_ORANK1[1]; + force d1r = INIT_ORANK1[0]; + end + else + begin + release d6rnk2; + release d5rnk2; + release d4rnk2; + release d3rnk2; + release d6r; + release d5r; + release d4r; + release d3r; + release d2r; + release d1r; + end +end + +///////////////////////////////////////// + + + +// Assign shiftout1 and shiftout2 + +assign SHIFTOUT1 = d3rnk2 & SERDES_MODE; + +assign SHIFTOUT2 = d4rnk2 & SERDES_MODE; + + + + + + +// last 4 flops which only have reset and init +// asynchronous operation +always @ (posedge C or posedge SR) +begin + begin + if (SR & !SRTYPE[2]) + begin + d3rnk2 <= # FFD 1'b0; + d4rnk2 <= # FFD 1'b0; + d5rnk2 <= # FFD 1'b0; + d6rnk2 <= # FFD 1'b0; + end + else if (!SRTYPE[2]) + begin + d3rnk2 <= # FFD data3; + d4rnk2 <= # FFD data4; + d5rnk2 <= # FFD data5; + d6rnk2 <= # FFD data6; + + end + end +end +// synchronous operation +always @ (posedge C) +begin + begin + if (SR & SRTYPE[2]) + begin + d3rnk2 <= # FFD 1'b0; + d4rnk2 <= # FFD 1'b0; + d5rnk2 <= # FFD 1'b0; + d6rnk2 <= # FFD 1'b0; + end + else if (SRTYPE[2]) + begin + d3rnk2 <= # FFD data3; + d4rnk2 <= # FFD data4; + d5rnk2 <= # FFD data5; + d6rnk2 <= # FFD data6; + + end + end +end + + + + + + + +/////////////////////////////////////////////////// +// First rank of flops for input data +////////////////////////////////////////////////// + +// asynchronous operation +always @ (posedge CLKDIV or posedge SR) +begin + begin + if (SR & !SRTYPE[3]) + begin + d1r <= # FFCD 1'b0; + d2r <= # FFCD 1'b0; + d3r <= # FFCD 1'b0; + d4r <= # FFCD 1'b0; + d5r <= # FFCD 1'b0; + d6r <= # FFCD 1'b0; + end + else if (!SRTYPE[3]) + begin + d1r <= # FFCD D1; + d2r <= # FFCD D2; + d3r <= # FFCD D3; + d4r <= # FFCD D4; + d5r <= # FFCD D5; + d6r <= # FFCD D6; + + end + end +end +// synchronous operation +always @ (posedge CLKDIV) +begin + begin + if (SR & SRTYPE[3]) + begin + d1r <= # FFCD 1'b0; + d2r <= # FFCD 1'b0; + d3r <= # FFCD 1'b0; + d4r <= # FFCD 1'b0; + d5r <= # FFCD 1'b0; + d6r <= # FFCD 1'b0; + end + else if (SRTYPE[3]) + begin + d1r <= # FFCD D1; + d2r <= # FFCD D2; + d3r <= # FFCD D3; + d4r <= # FFCD D4; + d5r <= # FFCD D5; + d6r <= # FFCD D6; + + end + end +end + +// Muxs for 2nd rank of flops +always @ (sel1_4 or d1r or d2rnk2 or d3rnk2) + begin + + casex (sel1_4) + 3'b100: data1 <= # MXR1 d3rnk2; + 3'b110: data1 <= # MXR1 d1r; + 3'b101: data1 <= # MXR1 d2rnk2; + 3'b111: data1 <= # MXR1 d1r; + default: data1 <= # MXR1 d3rnk2; + endcase + end + +always @ (sel1_4 or d2r or d3rnk2 or d4rnk2) + begin + casex (sel1_4) + 3'b100: data2 <= # MXR1 d4rnk2; + 3'b110: data2 <= # MXR1 d2r; + 3'b101: data2 <= # MXR1 d3rnk2; + 3'b111: data2 <= # MXR1 d2r; + default: data2 <= # MXR1 d4rnk2; + endcase + end + +//Note: To stop data rate of 00 from being illegal, register data is fed to mux +always @ (sel1_4 or d3r or d4rnk2 or d5rnk2) + begin + casex (sel1_4) + 3'b100: data3 <= # MXR1 d5rnk2; + 3'b110: data3 <= # MXR1 d3r; + 3'b101: data3 <= # MXR1 d4rnk2; + 3'b111: data3 <= # MXR1 d3r; + default: data3 <= # MXR1 d5rnk2; + endcase + end + +always @ (sel1_4 or d4r or d5rnk2 or d6rnk2) + begin + casex (sel1_4) + 3'b100: data4 <= # MXR1 d6rnk2; + 3'b110: data4 <= # MXR1 d4r; + 3'b101: data4 <= # MXR1 d5rnk2; + 3'b111: data4 <= # MXR1 d4r; + default: data4 <= # MXR1 d6rnk2; + endcase + end + +always @ (sel5_6 or d5r or d6rnk2 or SHIFTIN1) + begin + casex (sel5_6) + 4'b1000: data5 <= # MXR1 SHIFTIN1; + 4'b1010: data5 <= # MXR1 d5r; + 4'b1001: data5 <= # MXR1 d6rnk2; + 4'b1011: data5 <= # MXR1 d5r; + 4'b1100: data5 <= # MXR1 1'b0; + 4'b1110: data5 <= # MXR1 d5r; + 4'b1101: data5 <= # MXR1 d6rnk2; + 4'b1111: data5 <= # MXR1 d5r; + default: data5 <= # MXR1 SHIFTIN1; + endcase + end + +always @ (sel5_6 or D6 or d6r or SHIFTIN1 or SHIFTIN2) + begin + casex (sel5_6) + 4'b1000: data6 <= # MXR1 SHIFTIN2; + 4'b1010: data6 <= # MXR1 d6r; + 4'b1001: data6 <= # MXR1 SHIFTIN1; + 4'b1011: data6 <= # MXR1 d6r; + 4'b1100: data6 <= # MXR1 1'b0; + 4'b1110: data6 <= # MXR1 d6r; + 4'b1101: data6 <= # MXR1 1'b0; + 4'b1111: data6 <= # MXR1 d6r; + default: data6 <= # MXR1 SHIFTIN2; + endcase + end + + + + +// instantiate programmable load generator +plg_oserdese1_vlog ldgen (.c23(c23), .c45(c45), .c67(c67), .sel(sel), + .clk(C), .clkdiv(CLKDIV), .rst(SR), + .load(loadint), .IOCLK_GLITCH(IOCLK_GLITCH)); + +// Set value of counter in programmable load generator +always @ (plgcnt or c23 or c45 or c67 or sel) +begin + casex (plgcnt) + 5'b00100: begin c23=1'b0; c45=1'b0; c67=1'b0; sel=2'b00; end + 5'b00110: begin c23=1'b1; c45=1'b0; c67=1'b0; sel=2'b00; end + 5'b01000: begin c23=1'b0; c45=1'b0; c67=1'b0; sel=2'b01; end + 5'b01010: begin c23=1'b0; c45=1'b1; c67=1'b0; sel=2'b01; end + 5'b10010: begin c23=1'b0; c45=1'b0; c67=1'b0; sel=2'b00; end + 5'b10011: begin c23=1'b1; c45=1'b0; c67=1'b0; sel=2'b00; end + 5'b10100: begin c23=1'b0; c45=1'b0; c67=1'b0; sel=2'b01; end + 5'b10101: begin c23=1'b0; c45=1'b1; c67=1'b0; sel=2'b01; end + 5'b10110: begin c23=1'b0; c45=1'b0; c67=1'b0; sel=2'b10; end + 5'b10111: begin c23=1'b0; c45=1'b0; c67=1'b1; sel=2'b10; end + 5'b11000: begin c23=1'b0; c45=1'b0; c67=1'b0; sel=2'b11; end + default: $display("DATA_WIDTH %b and DATA_RATE_OQ %b at %t is an illegal value", DATA_WIDTH, DATA_RATE_OQ, $time); + endcase +end + +endmodule +`timescale 1ps/1ps +////////////////////////////////////////////////////////// +// +// module trif_oserdese1_vlog +// +///////////////////////////////////////////////////////// +// +// Inputs: +// +// T1, T2, T3, T4: tristate inputs +// load: Programmable load generator output +// TCE: Tristate clock enable +// SR: Set/Reset control. For the last 3 flops in TQ +// (qt1, qt2 and qt2n) this function is +// controlled bythe attributes SRVAL_TQ. In SERDES mode, +// SR is a RESET ONLY for all other flops! The flops will +// still be RESET even if SR is programmed to a SET! +// C, C2: High speed clocks +// C2 drives 2nd latch and C3 (inverse of C2) drives +// 3rd latch in output section +// CLKDIV: Low speed clock +// +// +// +// +// Outputs: +// +// TQ: Output of tristate mux +// +// +// Programmable Options: +// +// DATA_RATE_TQ: 2-bit field for types of operaiton +// 0 (buf from T1), 1 (registered output from T1), 2 (ddr) +// TRISTATE_WIDTH: 2-bit field for input width +// 0 (width 1), 1 (width 2), 2 (width 4) +// INIT_TQ: Init TQ output (0,1) +// SRVAL_TQ: This bit to controls value of SR input. +// Only the last 3 flops (qt1, qt2 and qt2n) are +// affected by this bit.For SERDES mode, this bit +// should be set to '0' making SR a reset. This is the +// desired state since all other flops only +// respond to this pin as a reset. Their function +// cannot be changed. SR is 'O' for SET and '1' for RESET. +// +// +// Programmable Test Options: +// SRTYPE: Control S and R as asynchronous (0) or synchronous (1) +// 2-bit value. 1st bit (msb) controls the 4 input flops +// and the 2nd bit (lsb) controls the "3 legacy flops" +// DDR_CLK_EDGE: Same or opposite edge operation +// +// +// +//////////////////////////////////////////////////////////////////////////////// +// + +module trif_oserdese1_vlog (T1, T2, T3, T4, load, + C, CLKDIV, SR, TCE, + DATA_RATE_TQ, TRISTATE_WIDTH, + INIT_TQ, SRVAL_TQ, + data1, data2); + +input T1, T2, T3, T4, load; + +input C, CLKDIV, SR, TCE; + +input [1:0] TRISTATE_WIDTH; + +input [1:0] DATA_RATE_TQ; + +input INIT_TQ, SRVAL_TQ; + +output data1, data2; + +wire DDR_CLK_EDGE; +wire [3:0] INIT_TRANK1; +wire [1:0] SRTYPE; +assign SRTYPE = 2'b11; +assign DDR_CLK_EDGE = 1'b1; +assign INIT_TRANK1 = 4'b0000; + +reg t1r, t2r, t3r, t4r; + +reg qt1, qt2, qt2n; + +reg data1, data2; + +reg sdata_edge, odata_edge, ddr_data; + +wire C2p, C3; + +wire load; + +wire [6:0] tqsel; + +wire [4:0] sel; + +assign sel = {load,DATA_RATE_TQ,TRISTATE_WIDTH}; + + + + + +////////////////////////////////////////////////// + + +// Parameters for gate delays +parameter ffd = 1; +parameter mxd = 1; + + +///////////////////////////// +// Initialization of Flops +//////////////////////////// + +tri0 GSR = glbl.GSR; + +always @(GSR) +begin + if (GSR) + begin + force t1r = INIT_TRANK1[0]; + force t2r = INIT_TRANK1[1]; + force t3r = INIT_TRANK1[2]; + force t4r = INIT_TRANK1[3]; + + end + else + begin + release t1r; + release t2r; + release t3r; + release t4r; + end +end + + + + +// First rank of flops +// asynchronous reset operation +always @ (posedge CLKDIV or posedge SR) +begin + begin + if (SR & !SRTYPE[1]) + begin + t1r <= # ffd 1'b0; + t2r <= # ffd 1'b0; + t3r <= # ffd 1'b0; + t4r <= # ffd 1'b0; + end + else if (!SRTYPE[1]) + begin + t1r <= # ffd T1; + t2r <= # ffd T2; + t3r <= # ffd T3; + t4r <= # ffd T4; + end + end +end + +// synchronous reset operation +always @ (posedge CLKDIV) +begin + begin + if (SR & SRTYPE[1]) + begin + t1r <= # ffd 1'b0; + t2r <= # ffd 1'b0; + t3r <= # ffd 1'b0; + t4r <= # ffd 1'b0; + end + else if (SRTYPE[1]) + begin + t1r <= # ffd T1; + t2r <= # ffd T2; + t3r <= # ffd T3; + t4r <= # ffd T4; + end + end +end + + + + + +// Data Muxs for tristate otuput signals +always @ (sel or T1 or t1r or t3r) + begin + + casex (sel) + 5'b00000: data1 <= # mxd T1; + 5'b10000: data1 <= # mxd T1; + 5'bX0000: data1 <= # mxd T1; + 5'b00100: data1 <= # mxd T1; + 5'b10100: data1 <= # mxd T1; + 5'bX0100: data1 <= # mxd T1; + 5'b01001: data1 <= # mxd T1; + 5'b11001: data1 <= # mxd T1; + 5'b01010: data1 <= # mxd t3r; + 5'b11010: data1 <= # mxd t1r; +// CR 551953 -- enabled TRISTATE_WIDTH to be 1 in DDR mode. No func change, but removed warnings + 5'b01000: ; + 5'b11000: ; + 5'bX1000: ; + + default: + begin + $display("DATA_RATE_TQ %b and/or TRISTATE_WIDTH %b at time %t are not supported by OSERDES", DATA_RATE_TQ,TRISTATE_WIDTH,$time); + $display("1.sel= %b",sel); + end + endcase + end +// For data 2, width of 1 is inserted as acceptable for buf and sdr +// The capability exists in the device if the feature is added +always @ (sel or T2 or t2r or t4r) + begin + casex (sel) + 5'b00000: data2 <= # mxd T2; + 5'b00100: data2 <= # mxd T2; + 5'b10000: data2 <= # mxd T2; + 5'b10100: data2 <= # mxd T2; + 5'bX0000: data2 <= # mxd T2; + 5'bX0100: data2 <= # mxd T2; + 5'b00X00: data2 <= # mxd T2; + 5'b10X00: data2 <= # mxd T2; + 5'bX0X00: data2 <= # mxd T2; + 5'b01001: data2 <= # mxd T2; + 5'b11001: data2 <= # mxd T2; + 5'bX1001: data2 <= # mxd T2; + 5'b01010: data2 <= # mxd t4r; + 5'b11010: data2 <= # mxd t2r; +// CR 551953 -- enabled TRISTATE_WIDTH to be 1 in DDR mode. No func change, but removed warnings + 5'b01000: ; + 5'b11000: ; + 5'bX1000: ; + + default: + begin + $display("DATA_RATE_TQ %b and/or TRISTATE_WIDTH %b at time %t are not supported by OSERDES", DATA_RATE_TQ,TRISTATE_WIDTH,$time); + $display("2.sel= %b",sel); + end + endcase + end + + +endmodule +`timescale 1ps/1ps +////////////////////////////////////////////////////////// +// +// module txbuffer_oserdese1_vlog +// +///////////////////////////////////////////////////////// +// +// FIFO and Control circuit for OSERDES + +module txbuffer_oserdese1_vlog (iodelay_state, qmux1, qmux2, tmux1, tmux2, + d1, d2, t1, t2, trif, + WC, ODV, extra, + clk, clkdiv, bufo, bufop, rst, + ODELAY_USED, DDR3_DATA, + DDR3_MODE); + +input d1, d2, t1, t2; + +input trif; + +input WC, ODV; + +input rst; + +input clk, clkdiv, bufo, bufop; + +input ODELAY_USED, DDR3_DATA; + +input DDR3_MODE; + +output iodelay_state, extra; + +output qmux1, qmux2, tmux1, tmux2; + +wire WC_DELAY; +assign WC_DELAY = 1'b0; + +wire rd_gap1; + +wire rst_bufo_p, rst_bufg_p; + + +wire rst_bufo_rc, rst_bufg_wc, rst_cntr, rst_bufop_rc; + +wire [1:0] qwc, qrd; + +wire bufo_out; + + +fifo_tdpipe_oserdese1_vlog data1 (.muxout(inv_qmux1), .din(~d1), .qwc(qwc), .qrd(qrd), + .rd_gap1(rd_gap1), + .bufg_clk(clk), .bufo_clk(bufo), .rst_bufo_p(rst_bufo_p), .rst_bufg_p(rst_bufg_p), + .DDR3_DATA(DDR3_DATA), .extra(extra), .ODV(ODV), .DDR3_MODE(DDR3_MODE) + + ); + +fifo_tdpipe_oserdese1_vlog data2 (.muxout(inv_qmux2), .din(~d2), .qwc(qwc), .qrd(qrd), + .rd_gap1(rd_gap1), + .bufg_clk(clk), .bufo_clk(bufo), .rst_bufo_p(rst_bufo_p), .rst_bufg_p(rst_bufg_p), + .DDR3_DATA(DDR3_DATA), .extra(extra), .ODV(ODV), .DDR3_MODE(DDR3_MODE) + + ); + +fifo_tdpipe_oserdese1_vlog tris1 (.muxout(inv_tmux1), .din(~t1), .qwc(qwc), .qrd(qrd), + .rd_gap1(rd_gap1), + .bufg_clk(clk), .bufo_clk(bufo), .rst_bufo_p(rst_bufo_p), .rst_bufg_p(rst_bufg_p), + .DDR3_DATA(DDR3_DATA), .extra(extra), .ODV(ODV), .DDR3_MODE(DDR3_MODE) + + ); + +fifo_tdpipe_oserdese1_vlog tris2 (.muxout(inv_tmux2), .din(~t2), .qwc(qwc), .qrd(qrd), + .rd_gap1(rd_gap1), + .bufg_clk(clk), .bufo_clk(bufo), .rst_bufo_p(rst_bufo_p), .rst_bufg_p(rst_bufg_p), + .DDR3_DATA(DDR3_DATA), .extra(extra), .ODV(ODV), .DDR3_MODE(DDR3_MODE) + + ); + +wire qmux1 = ~inv_qmux1; +wire qmux2 = ~inv_qmux2; +wire tmux1 = ~inv_tmux1; +wire tmux2 = ~inv_tmux2; + +fifo_reset_oserdese1_vlog rstckt (.rst_bufo_p(rst_bufo_p), .rst_bufo_rc(rst_bufo_rc), + .rst_bufg_p(rst_bufg_p), .rst_bufg_wc(rst_bufg_wc), + .rst_cntr(rst_cntr), + .bufg_clk(clk), .bufo_clk(bufo), .clkdiv(clkdiv), .rst(rst), + .divide_2(WC_DELAY), .bufop_clk(bufop), .rst_bufop_rc(rst_bufop_rc) + + ); + + + + +fifo_addr_oserdese1_vlog addcntr (.qwc(qwc), .qrd(qrd), .rd_gap1(rd_gap1), .rst_bufg_wc(rst_bufg_wc), .rst_bufo_rc(rst_bufo_rc), .bufg_clk(clk), .bufo_clk(bufo), + .data(DDR3_DATA), .extra(extra), .rst_bufop_rc(rst_bufop_rc), .bufop_clk(bufop) + + ); + + + +iodlyctrl_npre_oserdese1_vlog idlyctrl (.iodelay_state(iodelay_state), .bufo_out(bufo_out), .rst_cntr(rst_cntr), + .wc(WC), .trif(trif), + .rst(rst_bufg_p), .bufg_clk(clk), .bufo_clk(bufo), .bufg_clkdiv(clkdiv), + .ddr3_dimm(ODELAY_USED), .wl6(WC_DELAY) + ); + +endmodule +`timescale 1ps/1ps +//////////////////////////////////////////////////////// +// +// module fifo_tdpipe_oserdese1_vlog +// +//////////////////////////////////////////////////////// + +// FIFO for write path + +module fifo_tdpipe_oserdese1_vlog (muxout, din, qwc, qrd, + rd_gap1, + bufg_clk, bufo_clk, rst_bufo_p, rst_bufg_p, + DDR3_DATA, extra, ODV, DDR3_MODE + + ); + + +input din; + +input [1:0] qwc, qrd; + +input rd_gap1; + +input rst_bufo_p, rst_bufg_p; + +input bufg_clk, bufo_clk; + +input DDR3_DATA, ODV; + +input extra; + +input DDR3_MODE; + +output muxout; + + +reg muxout; + +reg qout1, qout2; + +reg qout_int, qout_int2; + +reg [4:1] fifo; + +reg cin1; + +reg omux; + +wire [2:0] sel; + +reg pipe1, pipe2; + +wire selqoi, selqoi2; + +wire [2:0] selmuxout; + + + + + + +// 4 flops that make up the basic FIFO. They are all clocked +// off of fast BUFG. The first flop is the top flop in the chain. +// The CE input is used to mux the inputs. If the flop is selected, +// CE is high and it takes data from the output of the mux. If the +// flop is not selected, it retains its data. + +always @ (posedge bufg_clk or posedge rst_bufg_p) + begin + if (rst_bufg_p) + begin + fifo <= #10 4'b0000; + end + else if (!qwc[1] & !qwc[0]) + begin + fifo <= #10 {fifo[4:2],din}; + end + else if (!qwc[1] & qwc[0]) + begin + fifo <= #10 {fifo[4:3],din,fifo[1]}; + end + else if (qwc[1] & qwc[0]) + begin + fifo <= #10 {fifo[4],din,fifo[2:1]}; + end + else if (qwc[1] & !qwc[0]) + begin + fifo <= #10 {din,fifo[3:1]}; + end + end + + + +// Capture stage top +// This is the top flop of the "3 flops" for ODDR. This flop, along with the read +// counter will be clocked off of bufo. A 4:1 mux wil decode the outputs of the +// read counter and load the write data. A subsequent 2:1 mux will decode between +// the fifo and the legacy operation + + +// OMUX + +always @ (qrd or fifo) + begin + case (qrd) + 2'b00: omux <= #10 fifo[1]; + 2'b01: omux <= #10 fifo[2]; + 2'b10: omux <= #10 fifo[4]; + 2'b11: omux <= #10 fifo[3]; + default: omux <= #10 fifo[1]; + endcase + end + + +always @ (posedge bufo_clk or posedge rst_bufo_p) + begin + if (rst_bufo_p) + begin + qout_int <= #10 1'b0; + qout_int2 <= #10 1'b0; + end + else + begin + qout_int <= #10 omux; + qout_int2 <= #10 qout_int; + end + end + +assign #10 selqoi = ODV | rd_gap1; + + +always @ (selqoi or qout_int or omux) + begin + case(selqoi) + 1'b0: qout1 <= #10 omux; + 1'b1: qout1 <= #10 qout_int; + default: qout1 <= #10 omux; + endcase + end + +assign #10 selqoi2 = ODV & rd_gap1; + +always @ (selqoi2 or qout_int2 or qout_int) + begin + case(selqoi2) + 1'b0: qout2 <= #10 qout_int; + 1'b1: qout2 <= #10 qout_int2; + default qout2 <= #10 qout_int; + endcase + end + + +assign #14 selmuxout = {DDR3_MODE,DDR3_DATA,extra}; + + +always @ (selmuxout or din or omux or qout1 or qout2) + begin + case (selmuxout) + 3'b000: muxout = #1 din; + 3'b001: muxout = #1 din; + 3'b010: muxout = #1 din; + 3'b011: muxout = #1 din; + 3'b100: muxout = #1 omux; + 3'b101: muxout = #1 omux; + 3'b110: muxout = #1 qout1; + 3'b111: muxout = #1 qout2; + default: muxout = #10 din; + endcase + end + + + +endmodule +`timescale 1ps/1ps +//////////////////////////////////////////////////////// +// +// module fifo_reset_oserdese1_vlog +// +//////////////////////////////////////////////////////// +// +// TX FIFO reset +// +// This design performs 2 functions. One function is to reset all the +// flops in the TX FIFO. The other function is to respond to the signal +// rst_cntr. This signal comes from iodlyctrl and will be used to initiate an +// orderly transition to switch the DQ/DQS I/O from and read to a write. +// This process is required only for DDR3 DIMM support because the IODELAY +// is used for both the inputs and the outputs. The signal from the +// squelch circuit is a present fabric output. An additional input +// indicating that a write command was issued will be +// required for all I/O to support this signal. +// +// This design uses an asynchronous reset to reset all flops. After the +// reset is disabled, a 0 is propagated through the pipe stages to terminate +// the reset. The first 2 flops run off of the clkdiv domain. Their output +// feeds a latch to cross between the clkdiv and bufg_clk domain. The pipe +// stage for the bufg_clk domain is 3 deep, where the last flop is the +// reset signal for the bufg_clk domain. The 2nd flop of the bufg_clk pipe +// is fed to 2 flops that are in the bufo_clk domain. The 2 flops are +// to resolve metastability between the 2 clock domains. +// +// The circuit to enable an orderly transition from read to write uses the +// PREAMBLE_SYNCHED output of a portion of the squelch circuit. This pulse +// will initiate the reset sequence and also generate an enable which will +// switch the IODELAY from an IDELAY to an ODELAY. Timing is as specified in +// the "State of the Union" presentation. +// +// + + +module fifo_reset_oserdese1_vlog (rst_bufo_p, rst_bufo_rc, + rst_bufg_p, rst_bufg_wc, + rst_cntr, + bufg_clk, bufo_clk, clkdiv, rst, + divide_2, bufop_clk, rst_bufop_rc + + ); + + +input rst_cntr; + +input rst; + +input bufg_clk, bufo_clk, clkdiv; + +input bufop_clk; + + +// Memory cell input to support divide by 1 operation +input divide_2; + + +output rst_bufo_p, rst_bufo_rc; +output rst_bufg_p, rst_bufg_wc; + +output rst_bufop_rc; + + +reg [1:0] clkdiv_pipe; + +reg bufg_pipe; + +reg rst_cntr_reg; + +reg [2:0] bufo_rst_p, bufo_rst_rc; + +reg [1:0] bufop_rst_rc; + +reg [1:0] bufg_rst_p, bufg_rst_wc; + +wire bufg_clkdiv_latch, ltint1, ltint2, ltint3; + +wire latch_in; + + + + + + + +// 2 stage pipe for clkdiv domain to allow user to properly +// time everything + + +always @ (posedge bufg_clk or posedge rst) + begin + if (rst) + begin + rst_cntr_reg <= #10 1'b0; + end + else + begin + rst_cntr_reg <= #10 rst_cntr; + end + end + + +always @ (posedge clkdiv or posedge rst) + begin + if (rst) + begin + clkdiv_pipe <= #10 2'b11; + end + else + begin + clkdiv_pipe <= #10 {clkdiv_pipe[0],1'b0}; + end + end + +// Latch to compensate for clkdiv and bufg_clk clock skew +// Built of actual gates + +assign #1 latch_in = clkdiv_pipe[1]; + +assign #1 bufg_clkdiv_latch = !(ltint1 && ltint3); +assign #1 ltint1 = !(latch_in && bufg_clk); +assign #1 ltint2 = !(ltint1 && bufg_clk); +assign #1 ltint3 = !(bufg_clkdiv_latch && ltint2); + + + + + +// BUFG flop to register latch signal +always @ (posedge bufg_clk or posedge rst) + begin + if (rst) + begin + bufg_pipe <= #10 1'b1; + end + else + begin + bufg_pipe <= #10 bufg_clkdiv_latch; + end + end + + + + +// BUFG clock domain resests + +always @ (posedge bufg_clk or posedge rst) + begin + if (rst) + begin + bufg_rst_p <= #10 2'b11; + end + else + begin + bufg_rst_p <= #10 {bufg_rst_p[0],bufg_pipe}; + end + end + + +always @ (posedge bufg_clk or posedge rst_cntr or posedge rst) + begin + if (rst || rst_cntr) + begin + bufg_rst_wc <= #10 2'b11; + end + else + begin + bufg_rst_wc <= #10 {bufg_rst_wc[0],bufg_pipe}; + end + end + + + +// BUFO clock domain Resets +always @ (posedge bufo_clk or posedge rst) + begin + if (rst) + begin + bufo_rst_p <= #10 3'b111; + end + else + begin + bufo_rst_p <= #10 {bufo_rst_p[1:0],bufg_pipe}; + end + end + +always @ (posedge bufo_clk or posedge rst or posedge rst_cntr) + begin + if (rst || rst_cntr) + begin + bufo_rst_rc <= #10 3'b111; + end + else + begin + bufo_rst_rc <= #10 {bufo_rst_rc[1:0],bufg_pipe}; + end + end + + + +always @ (posedge bufop_clk or posedge rst or posedge rst_cntr) + begin + if (rst || rst_cntr) + begin + bufop_rst_rc <= #10 2'b11; + end + else + begin + bufop_rst_rc <= #10 {bufop_rst_rc[0],bufg_pipe}; + end + end + + +// final reset assignments +assign rst_bufo_rc = bufo_rst_rc[1]; + +assign rst_bufo_p = bufo_rst_p[1]; + +assign rst_bufop_rc = bufop_rst_rc[1]; + +assign rst_bufg_wc = bufg_rst_wc[1]; + +assign rst_bufg_p = bufg_rst_p[1]; + + +endmodule +`timescale 1ps/1ps +//////////////////////////////////////////////////////// +// +// module fifo_addr_oserdese1_vlog +// +//////////////////////////////////////////////////////// +// Read and Write address generators for TX FIFO +// +// This circuit contains 2 greycode read and write address generators +// that will be used with the TX FIFO. Both counters generate a +// count sequence of 00 -> 01 -> 11 -> 10 -> 00. + + + +module fifo_addr_oserdese1_vlog (qwc, qrd, rd_gap1, rst_bufg_wc, rst_bufo_rc, bufg_clk, bufo_clk, + data, extra, rst_bufop_rc, bufop_clk + + ); + + +input bufg_clk, bufo_clk; + +input rst_bufo_rc, rst_bufg_wc; + +input rst_bufop_rc; + +input data; // mc to tell if I/O is DDR3 DQ or DQS + +input bufop_clk; + +output [1:0]qwc, qrd; // Scalar port ``qwc'' has a vectored net declaration [1:0] + +output rd_gap1, extra; + + + + +reg [1:0] qwc; // unisims/OSERDESE1.v:2073 error: Scalar port ``qwc'' has a vectored net declaration [1:0] + +reg [1:0] qrd; // unisims/OSERDESE1.v:2075: error: Scalar port ``qrd'' has a vectored net declaration [1:0] + + +reg stop_rd, rd_gap1, extra; + +reg rd_cor, rd_cor_cnt, rd_cor_cnt1; + + +wire qwc0_latch, qwc1_latch; + +wire li01, li02, li03; + +wire li11, li12, li13; + + +wire qwc0_latchn, qwc1_latchn; + +wire li01n, li02n, li03n; + +wire li11n, li12n, li13n; + + +reg stop_rdn, rd_cor_cntn, rd_cor_cnt1n, stop_rc; + + + + +reg [1:0] qwcd; + +reg [1:0] qrdd; + + +reg stop_rdd, rd_gap1d, extrad; + +reg rd_cord, rd_cor_cntd, rd_cor_cnt1d; + + +wire qwcd0_latch, qwcd1_latch; + +wire li01d, li02d, li03d; + +wire li11d, li12d, li13d; + + + +// Write counter +// The write counter uses 2 flops to create the grey code pattern of +// 00 -> 01 -> 11 -> 10 -> 00. The write counter is initialized +// to 11 and the read counter will be initialized to 00. This gives +// a basic 2 clock separation to compensate for the phase differences. +// The write counter is clocked off of the bufg clock + +always @ (posedge bufg_clk or posedge rst_bufg_wc) + begin + if (rst_bufg_wc) + begin + qwc <= # 10 2'b11; + end + else if (qwc[1] ^ qwc[0]) + begin + qwc[1] <= # 10 ~qwc[1]; + qwc[0] <= # 10 qwc[0]; + end + else + begin + qwc[1] <= # 10 qwc[1]; + qwc[0] <= # 10 ~qwc[0]; + end + end + + + + + + +// Read counter +// The read counter uses 2 flops to create the grey code pattern of +// 00 -> 01 -> 11 -> 10 -> 00. The read counter is initialized +// to 00 and the write counter will be initialized to 11. This gives +// a basic 2 clock separation to compensate for the phase differences. +// The read counter is clocked off of the bufo clock + +always @ (posedge bufo_clk or posedge rst_bufo_rc) + + begin + if (rst_bufo_rc) + begin + qrd <= # 10 2'b00; + end + else if (stop_rd && !data) + begin + qrd <= #10 qrd; + end + else if (qrd[1] ^ qrd[0]) + begin + qrd[1] <= # 10 ~qrd[1]; + qrd[0] <= # 10 qrd[0]; + end + else + begin + qrd[1] <= # 10 qrd[1]; + qrd[0] <= # 10 ~qrd[0]; + end + end + +always @ (posedge bufo_clk or posedge rst_bufo_rc) + + begin + if (rst_bufo_rc) + begin + rd_gap1 <= # 10 1'b0; + end +// else if ((qwc1_latch && qwc0_latch) && (qrd[0] ^ qrd[1])) + else if ((qwc1_latch && qwc0_latch) && (qrd[0])) + begin + rd_gap1 <= # 10 1'b1; + end + else + begin + rd_gap1 <= # 10 rd_gap1; + end + end + + + + + +// Looking for 11 + +assign #1 qwc0_latch = !(li01 & li03); +assign #1 li01 = !(qwc[0] & bufo_clk); +assign #1 li02 = !(li01 & bufo_clk); +assign #1 li03 = !(qwc0_latch & li02); + + +assign #1 qwc1_latch = !(li11 & li13); +assign #1 li11 = !(qwc[1] & bufo_clk); +assign #1 li12 = !(li11 & bufo_clk); +assign #1 li13 = !(qwc1_latch & li12); + + +// The following counter is to match the control counter to see if the +// read counter did a hold after reset. This knowledge will enable the +// computation of the 'extra' output. This in turn can add the +// proper number of pipe stages to the output. The circuit must use +// the output of BUFO and not be modified by ODELAY. This is because +// the control pins PP clock was not modified by BUFO. If the +// control pins PP clock was modified by BUFO, the reset must be done +// with this in mind. + +// Read counter +// The read counter uses 2 flops to create the grey code pattern of +// 00 -> 01 -> 11 -> 10 -> 00. The read counter is initialized +// to 00 and the write counter will be initialized to 11. This gives +// a basic 2 clock separation to compensate for the phase differences. +// The read counter is clocked off of the bufo clock + +always @ (posedge bufop_clk or posedge rst_bufop_rc) + + begin + if (rst_bufop_rc) + begin + qrdd <= # 10 2'b00; + end + else if (qrdd[1] ^ qrdd[0]) + begin + qrdd[1] <= # 10 ~qrdd[1]; + qrdd[0] <= # 10 qrdd[0]; + end + else + begin + qrdd[1] <= # 10 qrdd[1]; + qrdd[0] <= # 10 ~qrdd[0]; + end + end + + + +// Looking for 11 + +assign #1 qwcd0_latch = !(li01d & li03d); +assign #1 li01d = !(qwc[0] & bufop_clk); +assign #1 li02d = !(li01d & bufop_clk); +assign #1 li03d = !(qwcd0_latch & li02d); + + +assign #1 qwcd1_latch = !(li11d & li13d); +assign #1 li11d = !(qwc[1] & bufop_clk); +assign #1 li12d = !(li11d & bufop_clk); +assign #1 li13d = !(qwcd1_latch & li12d); + + + +// Circuit to fix read address counters in non data pins +always @ (posedge bufop_clk or posedge rst_bufo_rc) + + begin + if (rst_bufop_rc) + begin + stop_rd <= # 10 1'b0; + rd_cor_cnt <= #10 1'b0; + rd_cor_cnt1 <= #10 1'b0; + end + else if (((qwcd1_latch && qwcd0_latch) && (qrdd[0] ^ qrdd[1]) && !rd_cor_cnt1)) + begin + stop_rd <= #10 1'b1; + rd_cor_cnt <= #10 1'b1; + rd_cor_cnt1 <= #10 rd_cor_cnt; + end + else + begin + stop_rd <= #10 1'b0; + rd_cor_cnt <= #10 1'b1; + rd_cor_cnt1 <= #10 rd_cor_cnt; + end + end + +// Circuit to inform data if control counters habe been fixed + +always @ (posedge bufop_clk or posedge rst_bufop_rc) + begin + if (rst_bufop_rc) + begin + extra <= #10 1'b0; + end + else if (stop_rd) + begin + extra <= #10 1'b1; + end + end + +endmodule +`timescale 1ps/1ps +//////////////////////////////////////////////////////// +// +// module iodlyctrl_npre_oserdese1_vlog +// +//////////////////////////////////////////////////////// +// +// Circuit to automatically switch IODELAY from IDELAY to ODELAY using knowledge +// of write command. This circuit forces the user to wait 3 extra CLK/CLK# cycles +// when performing a read to write turnaround. The JEDEC DDR3 spec states that +// the turnaround can be done in 2 clock cycles. This circuit requires 5 clock +// cycles. +// This circuit is only used for a DDR3 appplication that uses DIMMs + + + +module iodlyctrl_npre_oserdese1_vlog (iodelay_state, bufo_out, rst_cntr, + wc, trif, + rst, bufg_clk, bufo_clk, bufg_clkdiv, + ddr3_dimm, wl6 + ); + + +input wc; + +input trif; + +input rst; + +input bufo_clk, bufg_clk, bufg_clkdiv; + +input ddr3_dimm, wl6; + +output iodelay_state, rst_cntr; + +output bufo_out; + + +reg qw0cd, qw1cd; + +reg turn, turn_p1; + +reg rst_cntr; + +reg w_to_w; + +reg [2:0] wtw_cntr; + +reg cmd0, cmd0_n6, cmd0_6, cmd1; + + + + +wire wr_cmd0; + +wire lt0int1, lt0int2, lt0int3; + +wire lt1int1, lt1int2, lt1int3; + +wire latch_in; + +reg qwcd; + + + + + +assign bufo_out = bufo_clk; + + +// create turn signal for IODELAY +assign iodelay_state = (trif && ~w_to_w) & ((~turn && ~turn_p1) || ~ddr3_dimm); + + + +// Registers to detect write command + +// Registers using bufg clkdiv +always @ (posedge bufg_clkdiv) +begin + if (rst) + begin + qwcd <= #10 0; + end + else + begin + qwcd <= #10 wc; + end +end + + + +// Latch to allow skew between CLK and CLKDIV from BUFGs +assign #1 wr_cmd0 = !(lt0int1 && lt0int3); +assign #1 lt0int1 = !(qwcd && bufg_clk); +assign #1 lt0int2 = !(lt0int1 && bufg_clk); +assign #1 lt0int3 = !(wr_cmd0 && lt0int2); + +always @ (posedge bufg_clk) + begin + if (rst) + begin + cmd0_n6 <= #10 1'b0; + cmd0_6 <= #10 1'b0; + end + else + begin + cmd0_n6 <= #10 wr_cmd0; + cmd0_6 <= #10 cmd0_n6; + end + end + + + +// mux to add extra pipe stage for WL = 6 +always @ (cmd0_n6 or wl6 or cmd0_6) + begin + case (wl6) + 1'b0: cmd0 <= #10 cmd0_n6; + 1'b1: cmd0 <= #10 cmd0_6; + default: cmd0 <= #10 cmd0_n6; + endcase + end + + +// Turn IODELAY and reset FIFO read/write counters +//always @ (posedge bufg_clk) +// begin +// if (rst) +// +// begin +// turn <= #10 1'b0; +// rst_cntr <= #10 1'b0; +// end +// else if (w_to_w) +// begin +// turn <= #10 1'b1; +// rst_cntr <= #10 1'b0; +// end +// else if (cmd0 && !turn) +// begin +// turn <= #10 1'b1; +// rst_cntr <= #10 1'b1; +// end +// else if (~trif) +// begin +// turn <= #10 1'b0; +// rst_cntr <= #10 1'b0; +// end +// else if (turn) +// begin +// turn <= #10 1'b1; +// rst_cntr <= #10 1'b0; +// end +// else +// begin +// turn <= #10 1'b0; +// rst_cntr <= #10 1'b0; +// end +// end + + + +always @ (posedge bufg_clk) +begin + begin + if (rst) + begin + turn <= #10 1'b0; + end + else + begin + turn <= #10 (w_to_w || (cmd0 && ~turn) || + (~wtw_cntr[2] && turn)); + end + + end + + begin + if (rst) + begin + rst_cntr <= #10 1'b0; + end + else + begin + rst_cntr <= #10 (~w_to_w && (cmd0 && ~turn)); + end + end +end + + + + +always @ (posedge bufg_clk) + begin + if (rst) + begin + turn_p1 <= #10 1'b0; + end + else + begin + turn_p1 <= #10 turn; + end + end + + + + +// Detect multiple write commands and don"t turn IODELAY +//always @ (posedge bufg_clk) +// begin +// if (rst) +// begin +// w_to_w <= #10 1'b0; +// wtw_cntr <= #10 3'b000; +// end +// else if (cmd0 && turn_p1) +// begin +// w_to_w <= #10 1'b1; +// wtw_cntr <= #10 3'b000; +// end +// else if (wtw_cntr == 3'b101) +// begin +// w_to_w <= #10 1'b0; +// wtw_cntr <= #10 3'b000; +// end +// else if (w_to_w) +// begin +// w_to_w <= #10 1'b1; +// wtw_cntr <= #10 wtw_cntr + 1; +// end +// end + + +always @ (posedge bufg_clk) +begin + begin + if (rst) + begin + w_to_w <= #10 1'b0; + end + else + begin + w_to_w <= #10 ((cmd0 && turn_p1) || + (w_to_w && (~wtw_cntr[2] || ~wtw_cntr[1]))); + end + end +end + + +always @ (posedge bufg_clk) + + begin + if (!(w_to_w || turn) || (cmd0 && turn_p1)) + begin + wtw_cntr <= #10 3'b000; + end + else if (w_to_w || turn_p1) + begin + wtw_cntr <= #10 wtw_cntr + 1; + end + end + +endmodule +`timescale 1ps/1ps +//////////////////////////////////////////////////////// +// +// MODULE dout_oserdese1_vlog +// +// This model ONLY works for SERDES operation!! +// Does not include tristate circuit +// +///////////////////////////////////////////////////////// +// +// Inputs: +// data1: Data from FIFO +// data2: Data input FIFO +// CLK: High speed clock from DCM +// BUFO: Clock from performance path +// OCE: Clock enable for output data flops +// SR: Set/Reset control. For the last 3 flops in OQ +// (d1rnk2, d2rnk2 and d2nrnk2) this function is +// controlled bythe attributes SRVAL_OQ. In SERDES mode, +// SR is a RESET ONLY for all other flops! The flops will +// still be RESET even if SR is programmed to a SET! +// +// +// +// Outputs: +// OQ: Data output +// +// +// +// Programmable Points +// DATA_RATE_OQ: Rate control for data output, 1-bit +// sdr (1), ddr (0) +// INIT_OQ: Init OQ output "flop" +// SRVAL_OQ: This bit to controls value of SR input. +// Only the last 3 flops (d1rnk2, d2rnk2 and d2nrnk2) +// are affected by this bit.For SERDES mode, this bit +// should be set to '0' making SR a reset. This is the +// desired state since all other flops only respond to +// this pin as a reset. Their function cannot be +// changed. SR is '1' for SET and '0' for RESET. +// +// +// +// Programmable points for Test model +// SRTYPE: This is a 4-bit field Sets asynchronous (0) or synchronous (1) set/reset +// 1st bit (msb) sets rank1 flops, 2nd bit sets 4 flops in rank 2, +// 3rd bit sets "3 legacy flops, and 4th (lsb) bit sets the counter +// DDR_CLK_EDGE: Controls use of 2 or 3 flops for single case. Default to 1 for +// SERDES operation +// +// +/////////////////////////////////////////////////////////////////////////////// +// + +module dout_oserdese1_vlog (data1, data2, + CLK, BUFO, SR, OCE, + OQ, d2rnk2, + DATA_RATE_OQ, + INIT_OQ, SRVAL_OQ, + DDR3_MODE); + +input data1, data2; + +input CLK, SR, OCE; + +input BUFO; + +input INIT_OQ, SRVAL_OQ; + +input DDR3_MODE; + +output OQ; + +output d2rnk2; + + +// Programmable Points + +input DATA_RATE_OQ; + +wire DDR_CLK_EDGE; +wire [3:0] SRTYPE; +assign DDR_CLK_EDGE = 1'b1; +assign SRTYPE = 4'b1111; +reg d1rnk2, d2rnk2, d2nrnk2; + +reg OQ; + +reg ddr_data, odata_edge, sdata_edge; + +reg c23, c45, c67; + +wire C; + +wire C2p, C3; + +wire [3:0] seloq; + +wire oqsr, oqrev; + +assign C = (BUFO & DDR3_MODE) | (CLK & !DDR3_MODE); + +assign C2p = (C & DDR_CLK_EDGE) | (!C & !DDR_CLK_EDGE); + +assign C3 = !C2p; + +assign seloq = {OCE,DATA_RATE_OQ,oqsr,oqrev}; + +assign oqsr = !SRTYPE[1] & SR & !SRVAL_OQ; + +assign oqrev = !SRTYPE[1] & SR & SRVAL_OQ; + + + +////////////////////////////////////////////////// +// Delay values +// +parameter FFD = 1; // clock to out delay for flip flops +// driven by clk +parameter FFCD = 1; // clock to out delay for flip flops +// driven by clkdiv +parameter MXD = 1; // 60 ps mux delay + +parameter MXR1 = 1; + +//////////////////////////////////////////// +// Initialization of flops with GSR for test model +/////////////////////////////////////////// + +tri0 GSR = glbl.GSR; + +always @(GSR) +begin + if (GSR) + begin + assign OQ = INIT_OQ; + assign d1rnk2 = INIT_OQ; + assign d2rnk2 = INIT_OQ; + assign d2nrnk2 = INIT_OQ; + end + else + begin + deassign OQ; + deassign d1rnk2; + deassign d2rnk2; + deassign d2nrnk2; + end +end + +///////////////////////////////////////// + + + + + + +///////////////////////////////////////// +// 3 flops to create DDR operations of 4 latches +//////////////////////////////////////// + +// Representation of top latch +// asynchronous operation +always @ (posedge C or posedge SR) +begin + begin + if (SR & !SRVAL_OQ & !SRTYPE[1]) + begin + d1rnk2 <= # FFD 1'b0; + end + else if (SR & SRVAL_OQ & !SRTYPE[1]) + begin + d1rnk2 <= # FFD 1'b1; + end + else if (!OCE & !SRTYPE[1]) + begin + d1rnk2 <= # FFD OQ; + end + else if (!SRTYPE[1]) + begin + d1rnk2 <= # FFD data1; + end + end +end + +// synchronous operation +always @ (posedge C) +begin + begin + + if (SR & !SRVAL_OQ & SRTYPE[1]) + begin + d1rnk2 <= # FFD 1'b0; + end + else if (SR & SRVAL_OQ & SRTYPE[1]) + begin + d1rnk2 <= # FFD 1'b1; + end + else if (!OCE & SRTYPE[1]) + begin + d1rnk2 <= # FFD OQ; + end + else if (SRTYPE[1]) + begin + d1rnk2 <= # FFD data1; + end + end +end + + + + +// Representation of 2nd latch +// asynchronous operation +always @ (posedge C2p or posedge SR) +begin + begin + if (SR & !SRVAL_OQ & !SRTYPE[1]) + begin + d2rnk2 <= # FFD 1'b0; + end + else if (SR & SRVAL_OQ & !SRTYPE[1]) + begin + d2rnk2 <= # FFD 1'b1; + end + else if (!OCE & !SRTYPE[1]) + begin + d2rnk2 <= # FFD OQ; + end + else if (!SRTYPE[1]) + begin + d2rnk2 <= # FFD data2; + end + end +end + +// synchronous operation +always @ (posedge C2p) +begin + begin + + if (SR & !SRVAL_OQ & SRTYPE[1]) + begin + d2rnk2 <= # FFD 1'b0; + end + else if (SR & SRVAL_OQ & SRTYPE[1]) + begin + d2rnk2 <= # FFD 1'b1; + end + else if (!OCE & SRTYPE[1]) + begin + d2rnk2 <= # FFD OQ; + end + else if (SRTYPE[1]) + begin + d2rnk2 <= # FFD data2; + end + end +end + + + + +// Representation of 3rd flop ( latch and output latch) +// asynchronous operation +always @ (posedge C3 or posedge SR) +begin + begin + if (SR & !SRVAL_OQ & !SRTYPE[1]) + begin + d2nrnk2 <= # FFD 1'b0; + end + else if (SR & SRVAL_OQ & !SRTYPE[1]) + begin + d2nrnk2 <= # FFD 1'b1; + end + else if (!OCE & !SRTYPE[1]) + begin + d2nrnk2 <= # FFD OQ; + end + else if (!SRTYPE[1]) + begin + d2nrnk2 <= # FFD d2rnk2; + end + end +end + +// synchronous operation +always @ (posedge C3) +begin + + begin + if (SR & !SRVAL_OQ & SRTYPE[1]) + begin + d2nrnk2 <= # FFD 1'b0; + end + else if (SR & SRVAL_OQ & SRTYPE[1]) + begin + d2nrnk2 <= # FFD 1'b1; + end + else if (!OCE & SRTYPE[1]) + begin + d2nrnk2 <= # FFD OQ; + end + else if (SRTYPE[1]) + begin + d2nrnk2 <= # FFD d2rnk2; + end + end +end + + +// Logic to generate same edge data from d1rnk2 and d2nrnk2; +always @ (C or C3 or d1rnk2 or d2nrnk2) + begin + sdata_edge <= # MXD (d1rnk2 & C) | (d2nrnk2 & C3); + end + +// Mux to create opposite edge DDR data from d1rnk2 and d2rnk2 +always @ (C or d1rnk2 or d2rnk2) + begin + case (C) + 1'b0: odata_edge <= # MXD d2rnk2; + 1'b1: odata_edge <= # MXD d1rnk2; + default: odata_edge <= # MXD d1rnk2; + endcase + end + +// Logic to same edge and opposite data into just ddr data +always @ (ddr_data or sdata_edge or odata_edge or DDR_CLK_EDGE) + begin + ddr_data <= # MXD (odata_edge & !DDR_CLK_EDGE) | (sdata_edge & DDR_CLK_EDGE); + end + + +// Output mux to generate OQ +always @ (seloq or d1rnk2 or ddr_data or OQ) + begin + casex (seloq) + 4'bXX01: OQ <= # MXD 1'b1; + 4'bXX10: OQ <= # MXD 1'b0; + 4'bXX11: OQ <= # MXD 1'b0; + 4'bX000: OQ <= # MXD ddr_data; + 4'bX100: OQ <= # MXD d1rnk2; + default: OQ <= # MXD ddr_data; + endcase + end + + +endmodule +`timescale 1ps/1ps +////////////////////////////////////////////////////////// +// +// module tout_oserdese1_vlog +// +// Tristate Output cell for Mt Blanc +// +// +//////////////////////////////////////////////////////// +// +// +// +///////////////////////////////////////////////////////// +// +// Inputs: +// +// data1, data2: tristate inputs +// TCE: Tristate clock enable +// SR: Set/Reset control. For the last 3 flops in TQ +// (qt1, qt2 and qt2n) this function is +// controlled bythe attributes SRVAL_TQ. In SERDES mode, +// SR is a RESET ONLY for all other flops! The flops will +// still be RESET even if SR is programmed to a SET! +// CLK: High speed clocks +// C2 drives 2nd latch and C3 (inverse of C2) drives +// 3rd latch in output section +// BUFO: Performance path clock +// +// +// +// +// Outputs: +// +// TQ: Output of tristate mux +// +// +// Programmable Options: +// +// DATA_RATE_TQ: 2-bit field for types of operaiton +// 0 (buf from T1), 1 (registered output from T1), 2 (ddr) +// TRISTATE_WIDTH: 2-bit field for input width +// 0 (width 1), 1 (width 2), 2 (width 4) +// INIT_TQ: Init TQ output (0,1) +// SRVAL_TQ: This bit to controls value of SR input. +// Only the last 3 flops (qt1, qt2 and qt2n) are +// affected by this bit.For SERDES mode, this bit +// should be set to '0' making SR a reset. This is the +// desired state since all other flops only +// respond to this pin as a reset. Their function +// cannot be changed. SR is 'O' for SET and '1' for RESET. +// +// +// Programmable Test Options: +// SRTYPE: Control S and R as asynchronous (0) or synchronous (1) +// 2-bit value. 1st bit (msb) controls the 4 input flops +// and the 2nd bit (lsb) controls the "3 legacy flops" +// DDR_CLK_EDGE: Same or opposite edge operation +// +// +// +//////////////////////////////////////////////////////////////////////////////// +// + +module tout_oserdese1_vlog (data1, data2, + CLK, BUFO, SR, TCE, + DATA_RATE_TQ, TRISTATE_WIDTH, + INIT_TQ, SRVAL_TQ, + TQ, DDR3_MODE); + +input data1, data2; + +input CLK, BUFO, SR, TCE; + +input [1:0] DATA_RATE_TQ, TRISTATE_WIDTH; + +input INIT_TQ, SRVAL_TQ; + +input DDR3_MODE; + +output TQ; + +wire DDR_CLK_EDGE; +wire [1:0] SRTYPE; +assign SRTYPE = 2'b11; +assign DDR_CLK_EDGE = 1'b1; + +reg TQ; + +reg t1r, t2r, t3r, t4r; + +reg qt1, qt2, qt2n; + +reg sdata_edge, odata_edge, ddr_data; + +wire C; + +wire C2p, C3; + +wire load; + +wire [5:0] tqsel; + +wire tqsr, tqrev; + +wire [4:0] sel; + +assign C = (BUFO & DDR3_MODE) | (CLK & !DDR3_MODE); + +assign C2p = (C & DDR_CLK_EDGE) | (!C & !DDR_CLK_EDGE); + +assign C3 = !C2p; + +assign tqsr = (!SRTYPE[0] & SR & !SRVAL_TQ) | (!SRTYPE[0] & SRVAL_TQ); + +assign tqrev = (!SRTYPE[0] & SR & SRVAL_TQ) | (!SRTYPE[0] & !SRVAL_TQ); + +assign tqsel = {TCE,DATA_RATE_TQ,TRISTATE_WIDTH,tqsr}; + + + + + +////////////////////////////////////////////////// + + +// Parameters for gate delays +parameter ffd = 1; +parameter mxd = 1; + + +///////////////////////////// +// Initialization of Flops +//////////////////////////// + +tri0 GSR = glbl.GSR; + +always @(GSR) +begin + if (GSR) + begin + assign TQ = INIT_TQ; + assign qt1 = INIT_TQ; + assign qt2 = INIT_TQ; + assign qt2n = INIT_TQ; + end + else + begin + deassign TQ; + deassign qt1; + deassign qt2; + deassign qt2n; + end +end + + + +///////////////////////////////////////// +// 3 flops to create DDR operations of 4 latches +//////////////////////////////////////// + +// Representation of top latch +// asynchronous operation +always @ (posedge C or posedge SR) +begin + begin + if (SR & !SRVAL_TQ & !SRTYPE[0]) + begin + qt1 <= # ffd 1'b0; + end + else if (SR & SRVAL_TQ & !SRTYPE[0]) + begin + qt1 <= # ffd 1'b1; + end + else if (!TCE & !SRTYPE[0]) + begin + qt1 <= # ffd TQ; + end + else if (!SRTYPE[0]) + begin + qt1 <= # ffd data1; + end + end +end + +// synchronous operation +always @ (posedge C) +begin + begin + + if (SR & !SRVAL_TQ & SRTYPE[0]) + begin + qt1 <= # ffd 1'b0; + end + else if (SR & SRVAL_TQ & SRTYPE[0]) + begin + qt1 <= # ffd 1'b1; + end + else if (!TCE & SRTYPE[0]) + begin + qt1 <= # ffd TQ; + end + else if (SRTYPE[0]) + begin + qt1 <= # ffd data1; + end + end +end + + + + +// Representation of 2nd latch +// asynchronous operation +always @ (posedge C2p or posedge SR) +begin + begin + if (SR & !SRVAL_TQ & !SRTYPE[0]) + begin + qt2 <= # ffd 1'b0; + end + else if (SR & SRVAL_TQ & !SRTYPE[0]) + begin + qt2 <= # ffd 1'b1; + end + else if (!TCE & !SRTYPE[0]) + begin + qt2 <= # ffd TQ; + end + else if (!SRTYPE[0]) + begin + qt2 <= # ffd data2; + end + end +end + +// synchronous operation +always @ (posedge C2p) +begin + begin + if (SR & !SRVAL_TQ & SRTYPE[0]) + begin + qt2 <= # ffd 1'b0; + end + else if (SR & SRVAL_TQ & SRTYPE[0]) + begin + qt2 <= # ffd 1'b1; + end + else if (!TCE & SRTYPE[0]) + begin + qt2 <= # ffd TQ; + end + else if (SRTYPE[0]) + begin + qt2 <= # ffd data2; + end + end +end + + + + +// Representation of 3rd flop ( latch and output latch) +// asynchronous operation +always @ (posedge C3 or posedge SR) +begin + begin + if (SR & !SRVAL_TQ & !SRTYPE[0]) + begin + qt2n <= # ffd 1'b0; + end + else if (SR & SRVAL_TQ & !SRTYPE[0]) + begin + qt2n <= # ffd 1'b1; + end + else if (!TCE & !SRTYPE[0]) + begin + qt2n <= # ffd TQ; + end + else if (!SRTYPE[0]) + begin + qt2n <= # ffd qt2; + end + end +end + +// synchronous operation +always @ (posedge C3) +begin + + begin + if (SR & !SRVAL_TQ & SRTYPE[0]) + begin + qt2n <= # ffd 1'b0; + end + else if (SR & SRVAL_TQ & SRTYPE[0]) + begin + qt2n <= # ffd 1'b1; + end + else if (!TCE & SRTYPE[0]) + begin + qt2n <= # ffd TQ; + end + else if (SRTYPE[0]) + begin + qt2n <= # ffd qt2; + end + end +end + + +// Logic to generate same edge data from qt1, qt3; +always @ (C or C3 or qt1 or qt2n) + begin + sdata_edge <= # mxd (qt1 & C) | (qt2n & C3); + end + +// Mux to create opposite edge DDR function +always @ (C or qt1 or qt2) + begin + case (C) + 1'b0: odata_edge <= # mxd qt2; + 1'b1: odata_edge <= # mxd qt1; + default: odata_edge <= 1'b0; + endcase + end + +// Logic to same edge and opposite data into just ddr data +always @ (ddr_data or sdata_edge or odata_edge or DDR_CLK_EDGE) + begin + ddr_data <= # mxd (odata_edge & !DDR_CLK_EDGE) | (sdata_edge & DDR_CLK_EDGE); + end + +// Output mux to generate TQ +// Note that the TQ mux can also support T2 combinatorial or +// registered outputs. +always @ (tqsel or data1 or ddr_data or qt1 or TQ) + begin + casex (tqsel) + 6'bX01XX1: TQ <= # mxd 1'b0; + 6'bX10XX1: TQ <= # mxd 1'b0; + 6'bX01XX1: TQ <= # mxd 1'b0; + 6'bX10XX1: TQ <= # mxd 1'b0; + 6'bX0000X: TQ <= # mxd data1; + // 6'b001000: TQ <= # mxd TQ; + // 6'b010010: TQ <= # mxd TQ; + // 6'b010100: TQ <= # mxd TQ; + 6'bX01000: TQ <= # mxd qt1; + 6'bX10010: TQ <= # mxd ddr_data; + 6'bX10100: TQ <= # mxd ddr_data; + default: TQ <= # mxd ddr_data; + endcase + end + + +endmodule + +`endcelldefine