290 lines
9.8 KiB
Verilog
Executable File
290 lines
9.8 KiB
Verilog
Executable File
`timescale 1 ps / 1 ps
|
|
|
|
module OSERDESE2_model (
|
|
// Clocks and reset
|
|
input wire CLK,
|
|
input wire CLKDIV,
|
|
input wire RST,
|
|
// D1 - D8: Parallel data inputs
|
|
input wire D1,
|
|
input wire D2,
|
|
input wire D3,
|
|
input wire D4,
|
|
input wire D5,
|
|
input wire D6,
|
|
input wire D7,
|
|
input wire D8,
|
|
// Buffer input/output for tristate controlle
|
|
input wire T1,
|
|
output reg TQ,
|
|
// Serial output
|
|
output wire OFB,
|
|
output reg OQ,
|
|
|
|
// NOT MODELLED
|
|
output wire SHIFTOUT1,
|
|
output wire SHIFTOUT2,
|
|
output wire TBYTEOUT,
|
|
output wire TFB,
|
|
input wire OCE,
|
|
input wire TCE,
|
|
input wire SHIFTIN1,
|
|
input wire SHIFTIN2,
|
|
input wire T2,
|
|
input wire T3,
|
|
input wire T4,
|
|
input wire TBYTEIN
|
|
);
|
|
parameter DATA_RATE_OQ = "DDR";
|
|
parameter DATA_RATE_TQ = "DDR";
|
|
parameter integer DATA_WIDTH = 4;
|
|
parameter [0:0] INIT_OQ = 1'b0;
|
|
parameter [0:0] INIT_TQ = 1'b0;
|
|
parameter integer TRISTATE_WIDTH = 4;
|
|
`ifdef NO_TEST_MODEL
|
|
parameter TEST_MODEL = 0;
|
|
`else
|
|
parameter TEST_MODEL = 1;
|
|
`endif
|
|
|
|
// stop simulation if this modelfile does not support the settings
|
|
initial begin
|
|
if(DATA_RATE_OQ == "SDR" && DATA_WIDTH != 4) begin
|
|
$display("DATA_WIDTH must be 4 if DATA_RATE_OQ is SDR");
|
|
$stop;
|
|
end
|
|
if(DATA_RATE_OQ == "DDR" && DATA_WIDTH != 8) begin
|
|
$display("DATA_WIDTH must be 8 if DATA_RATE_OQ is DDR");
|
|
$stop;
|
|
end
|
|
end
|
|
|
|
reg[7:0] D_clkdiv_q;
|
|
reg[7:0] D_clk_q;
|
|
reg[2:0] counter = 0;
|
|
reg clk_delayed;
|
|
reg D1_delayed;
|
|
reg D2_delayed;
|
|
reg D3_delayed;
|
|
reg D4_delayed;
|
|
reg D5_delayed;
|
|
reg D6_delayed;
|
|
reg D7_delayed;
|
|
reg D8_delayed;
|
|
|
|
always @(CLK) clk_delayed <= #100 CLK;
|
|
always @(D1) D1_delayed <= #100 D1;
|
|
always @(D2) D2_delayed <= #100 D2;
|
|
always @(D3) D3_delayed <= #100 D3;
|
|
always @(D4) D4_delayed <= #100 D4;
|
|
always @(D5) D5_delayed <= #100 D5;
|
|
always @(D6) D6_delayed <= #100 D6;
|
|
always @(D7) D7_delayed <= #100 D7;
|
|
always @(D8) D8_delayed <= #100 D8;
|
|
always @(T1) TQ <= #100 T1;
|
|
|
|
generate
|
|
//---------------------------------------------------------------------------------------//
|
|
//----------------------------------- DATA RATE = DDR -----------------------------------//
|
|
//---------------------------------------------------------------------------------------//
|
|
if(DATA_RATE_OQ == "DDR") begin
|
|
// reset the counter on CLKDIV posedge to make sure first CLK posedge has counter == 0
|
|
always @(posedge CLKDIV) begin
|
|
if(RST) begin
|
|
counter <= 0;
|
|
end
|
|
end
|
|
|
|
// serialize out the D_clk_q on both edges
|
|
always @(posedge clk_delayed or negedge clk_delayed) begin
|
|
OQ <= D_clk_q[counter];
|
|
if(!(counter == 0 && !clk_delayed)) begin // should never happen where counter will increment up from zero @negedge (only @posedge will 0 increments to 1)
|
|
counter <= counter + 1; // counts from 0->1->2->...->7->0..
|
|
end
|
|
end
|
|
|
|
always @(posedge CLK) begin
|
|
if(counter == 0) begin // store D1-D8 at first CLK posedge after CLKDIV posedge (in short the time when counter == 0)
|
|
D_clkdiv_q <= {D8,D7,D6,D5,D4,D3,D2,D1};
|
|
D_clk_q <= D_clkdiv_q;
|
|
end
|
|
if(RST) begin
|
|
D_clkdiv_q <= 0;
|
|
D_clk_q <= 0;
|
|
end
|
|
end
|
|
// OFB output is just same as OQ
|
|
assign OFB = OQ;
|
|
|
|
if(TEST_MODEL == 1) begin // if model needs to be tested if it matches with the outputs from actual OSERDES primitive
|
|
wire OQ_test, TQ_test;
|
|
reg unequal = 0;
|
|
|
|
OSERDESE2 #(
|
|
.DATA_RATE_OQ("DDR"), // DDR, SDR
|
|
.DATA_RATE_TQ("BUF"), // DDR, SDR
|
|
.DATA_WIDTH(8), // Parallel data width (2-8,10,14)
|
|
.INIT_OQ(1'b0), // Initial value of OQ output (1'b0,1'b1)
|
|
.TRISTATE_WIDTH(1)
|
|
)
|
|
OSERDESE2_test_model_ddr(
|
|
.OFB(), // 1-bit output: Feedback path for data
|
|
.OQ(OQ_test), // 1-bit output: Data path output
|
|
.CLK(CLK), // 1-bit input: High speed clock
|
|
.CLKDIV(CLKDIV), // 1-bit input: Divided clock
|
|
// D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
|
|
.D1(D1),
|
|
.D2(D2),
|
|
.D3(D3),
|
|
.D4(D4),
|
|
.D5(D5),
|
|
.D6(D6),
|
|
.D7(D7),
|
|
.D8(D8),
|
|
.TCE(1'b0),
|
|
.OCE(1'b1), // 1-bit input: Output data clock enable
|
|
.RST(RST), // 1-bit input: Reset
|
|
// unused signals but were added here to make vivado happy
|
|
.SHIFTOUT1(), // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
|
|
.SHIFTOUT2(),
|
|
.TBYTEOUT(), // 1-bit output: Byte group tristate
|
|
.TFB(), // 1-bit output: 3-state control
|
|
.TQ(TQ_test), // 1-bit output: 3-state control
|
|
// SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
|
|
.SHIFTIN1(0),
|
|
.SHIFTIN2(0),
|
|
// T1 - T4: 1-bit (each) input: Parallel 3-state inputs
|
|
.T1(T1),
|
|
.T2(0),
|
|
.T3(0),
|
|
.T4(0),
|
|
.TBYTEIN(0)
|
|
// 1-bit input: Byte group tristate
|
|
);
|
|
|
|
// check if OQ and TQ matches with the actual OSERDES primitive, if not then stop simulation
|
|
always @* begin
|
|
#1;
|
|
if((OQ !== OQ_test) && (RST === 0) && ($time > 500_000)) begin
|
|
$display("OSERDES OQ MODEL does not match: time = %t", $time);
|
|
unequal <= 1;
|
|
$stop;
|
|
end
|
|
if((TQ !== TQ_test) && (RST === 0) && ($time > 500_000)) begin
|
|
$display("OSERDES TQ MODEL does not match: time = %t", $time);
|
|
unequal <= 1;
|
|
$stop;
|
|
end
|
|
end
|
|
initial begin
|
|
$display("---------------------------------------- TESTING OSERDESE2 Model ----------------------------------------");
|
|
end
|
|
end // end of if(TEST_MODEL == 1)
|
|
end // end of if(DATA_RATE_OQ == "DDR")
|
|
|
|
|
|
//---------------------------------------------------------------------------------------//
|
|
//----------------------------------- DATA RATE = SDR -----------------------------------//
|
|
//---------------------------------------------------------------------------------------//
|
|
if(DATA_RATE_OQ == "SDR") begin
|
|
// reset the counter on CLKDIV posedge to make sure first CLK posedge has counter == 0
|
|
always @(posedge CLKDIV) begin
|
|
if(RST) begin
|
|
counter <= 0;
|
|
end
|
|
end
|
|
|
|
// serialize out the D_clk_q on both edges
|
|
always @(posedge clk_delayed) begin
|
|
case(counter)
|
|
0: OQ <= D_clk_q[0];
|
|
1: OQ <= D_clk_q[1];
|
|
2: OQ <= D_clk_q[2];
|
|
3: OQ <= D_clk_q[3];
|
|
endcase
|
|
counter <= (counter == 3)? 0: counter + 1; // mod-4 counter
|
|
end
|
|
|
|
always @(posedge CLK) begin
|
|
if(counter == 0) begin // store D1-D8 at first CLK posedge after CLKDIV posedge (in short the time when counter == 0)
|
|
D_clkdiv_q <= {D4,D3,D2,D1};
|
|
end
|
|
if(counter == 0) begin
|
|
D_clk_q <= D_clkdiv_q;
|
|
end
|
|
if(RST) begin
|
|
D_clkdiv_q <= 0;
|
|
D_clk_q <= 0;
|
|
end
|
|
end
|
|
// OFB output is just same as OQ
|
|
assign OFB = OQ;
|
|
|
|
if(TEST_MODEL == 1) begin // if model needs to be tested if it matches with the outputs from actual OSERDES primitive
|
|
wire OQ_test, TQ_test;
|
|
reg unequal = 0;
|
|
|
|
OSERDESE2 #(
|
|
.DATA_RATE_OQ("SDR"), // DDR, SDR
|
|
.DATA_RATE_TQ("SDR"), // DDR, SDR
|
|
.DATA_WIDTH(4), // Parallel data width (2-8,10,14)
|
|
.INIT_OQ(1'b0), // Initial value of OQ output (1'b0,1'b1)
|
|
.TRISTATE_WIDTH(1)
|
|
)
|
|
OSERDESE2_test_model_sdr(
|
|
.OFB(), // 1-bit output: Feedback path for data
|
|
.OQ(OQ_test), // 1-bit output: Data path output
|
|
.CLK(CLK), // 1-bit input: High speed clock
|
|
.CLKDIV(CLKDIV), // 1-bit input: Divided clock
|
|
// D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
|
|
.D1(D1),
|
|
.D2(D2),
|
|
.D3(D3),
|
|
.D4(D4),
|
|
.TCE(1'b0),
|
|
.OCE(1'b1), // 1-bit input: Output data clock enable
|
|
.RST(RST), // 1-bit input: Reset
|
|
// unused signals but were added here to make vivado happy
|
|
.SHIFTOUT1(), // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
|
|
.SHIFTOUT2(),
|
|
.TBYTEOUT(), // 1-bit output: Byte group tristate
|
|
.TFB(), // 1-bit output: 3-state control
|
|
.TQ(TQ_test), // 1-bit output: 3-state control
|
|
// SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
|
|
.SHIFTIN1(0),
|
|
.SHIFTIN2(0),
|
|
// T1 - T4: 1-bit (each) input: Parallel 3-state inputs
|
|
.T1(T1),
|
|
.T2(0),
|
|
.T3(0),
|
|
.T4(0),
|
|
.TBYTEIN(0)
|
|
// 1-bit input: Byte group tristate
|
|
);
|
|
|
|
// check if OQ and TQ matches with the actual OSERDES primitive, if not then stop simulation
|
|
always @* begin
|
|
#1;
|
|
if((OQ !== OQ_test) && (RST === 0) && ($time > 500_000)) begin
|
|
$display("OSERDES OQ MODEL does not match: time = %t", $time);
|
|
unequal <= 1;
|
|
$stop;
|
|
end
|
|
if((TQ !== TQ_test) && (RST === 0) && ($time > 500_000)) begin
|
|
$display("OSERDES TQ MODEL does not match: time = %t", $time);
|
|
unequal <= 1;
|
|
$stop;
|
|
end
|
|
end
|
|
initial begin
|
|
$display("---------------------------------------- TESTING OSERDESE2 Model ----------------------------------------");
|
|
end
|
|
end // end of if(TEST_MODEL == 1)
|
|
end // end of if(DATA_RATE_OQ == "SDR")
|
|
|
|
endgenerate
|
|
|
|
|
|
endmodule
|
|
|