EnderW4785
Member level 1
I've spent some time looking through the example code and I think I more or less understand how its supposed to work, but I'm still clearly missing something. My code does not simulate as expected. I have the following main module:
module main(
// input clocks for PLL
input wire clkADC_p,
input wire clkADC_n,
input wire clkWall,
// input LVDS bit rate clock
input wire clkin_p,
input wire clkin_n,
//input LVDS frame clock
input wire clkFrame_p,
input wire clkFrame_n,
//input LVDS data
input wire [1:0] datain_p,
input wire [1:0] datain_n,
//LVDS reset
input reset,
//output clock control for PLL
output wire vxcoCtrl,
//output wire div_clk,
//ouput deserialized data
output wire [15:0] dataout,
// Indicator that program was successful
output wire LEDIndicator);
// Begin main program
// ADC clock
wire clkADC;
wire div_clk;
// Divided down ADC clock by divisor
reg [25:0] divisor = 1382400;
parameter integer S = 8 ; // Set the serdes factor to 8
parameter integer C = 0 + 1; // Set the number of channels (increment by one for drive)
parameter integer D = 2*C ; // Set the number LVDS inputs = 2 * number of channels
parameter integer DS = (D*S)-1; // Used for bus widths = serdes factor * number of inputs - 1
wire [DS:0] rxd ; // Data from serdeses
wire [S-1:0] rxf ; // Recieved Data from Frame Clock
reg state ;
reg bslip ;
reg [3:0] count ;
assign rst = reset ; // active high reset pin
// turn on LED indicator to show successful programming
assign LEDIndicator = 1'b1;
// Configure differential PECL clock input
IBUFDS #(
.CAPACITANCE("DONT_CARE"),
.DIFF_TERM("FALSE"),
.IBUF_DELAY_VALUE("0"),
.IFD_DELAY_VALUE("AUTO"),
.IOSTANDARD("LVPECL_33"))
IBUFDS_inst1 (
.O(clkADC),
.I(clkADC_p),
.IB(clkADC_n));
// Perform clock divider
clk_divider clk_divider_inst (
.clk(clkADC),
.divisor(divisor),
.div_clk(div_clk));
// do PLL clock phase comparison
assign vxcoCtrl = div_clk ^ clkWall;
//Clock Input. Generate ioclocks via BUFIO2
serdes_1_to_n_clk_ddr_s8_diff #(
.S (S), // Set the serdes factor to 8
.DIFF_TERM ("TRUE")) // Enable or disable diff termination
inst_clkin (
.clkin_p (clkin_p),
.clkin_n (clkin_n),
.rxioclkp (rxioclkp),
.rxioclkn (rxioclkn),
.rx_serdesstrobe (rx_serdesstrobe),
.rx_bufg_x1 (rx_bufg_x1));
// Data Inputs
serdes_1_to_n_data_ddr_s8_diff #(
.S (S),
.D (D),
.DIFF_TERM ("TRUE")) // Enable or disable diff termination
inst_datain (
.use_phase_detector (1'b1), // '1' enables the phase detector logic
.datain_p (datain_p),
.datain_n (datain_n),
.rxioclkp (rxioclkp),
.rxioclkn (rxioclkn),
.rxserdesstrobe (rx_serdesstrobe),
.gclk (rx_bufg_x1),
.bitslip (bslip),
.reset (rst),
.data_out (rxd),
.debug_in (2'b00),
.debug ());
// Frame clock to use in logic of bitslip
// Data Inputs
serdes_1_to_n_data_ddr_s8_diff #(
.S (S),
.D (1),
.DIFF_TERM ("TRUE")) // Enable or disable diff termination
inst_frameclk (
.use_phase_detector (1'b1), // '1' enables the phase detector logic
.datain_p (clkFrame_p),
.datain_n (clkFrame_n),
.rxioclkp (rxioclkp),
.rxioclkn (rxioclkn),
.rxserdesstrobe (rx_serdesstrobe),
.gclk (rx_bufg_x1),
.bitslip (bslip),
.reset (rst),
.data_out (rxf),
.debug_in (2'b00),
.debug ());
always @ (posedge rx_bufg_x1 or posedge rst) // example bitslip logic, if required
begin
if (reset == 1'b1) begin
state <= 0 ;
bslip <= 1'b0 ;
count <= 4'b0000 ;
end
else begin
if (state == 0) begin
if (rxf[S-1:0] != 8'b00000000 & rxf[S-1:0] != 8'b11111111) begin
bslip <= 1'b1 ; // bitslip needed
state <= 1 ;
count <= 4'b0000 ;
end
end
else if (state == 1) begin
bslip <= 1'b0 ; // bitslip low
count <= count + 4'b0001 ;
if (count == 4'b1111) begin
state <= 0;
end
end
end
end
//output deserialized data
assign dataout = rxd;
endmodule
With the following test module:
module main_tb ();
// Inputs
reg clkADC_p; //ADC clock
reg clkADC_n;
reg clkWall; //60 Hz clock
reg clkin_p; //LVDS bit clock from ADC
reg clkin_n;
reg clkFrame_p; //LVDS frame clock from ADC
reg clkFrame_n;
reg [1:0] datain_p; //LVDS datain
reg [1:0] datain_n;
reg reset; //reset signal for LVDS deserialization block
// Outputs
wire vxcoCtrl; //Output control signal for the clock PLL
wire [15:0] dataout; //Deserialized data out
//wire div_clk;
wire LEDIndicator; //successful programming
// Instantiate the Unit Under Test (UUT)
main uut (
.clkADC_p(clkADC_p),
.clkADC_n(clkADC_n),
.clkWall(clkWall),
.clkin_p(clkin_p),
.clkin_n(clkin_n),
.clkFrame_p(clkFrame_p),
.clkFrame_n(clkFrame_n),
.datain_p(datain_p),
.datain_n(datain_n),
.reset(reset),
.vxcoCtrl(vxcoCtrl),
.dataout(dataout),
//.div_clk(div_clk),
.LEDIndicator(LEDIndicator)
);
initial begin
// Initialize Inputs
clkADC_p = 1;
clkADC_n = 0;
clkWall = 1;
clkin_p = 1;
clkin_n = 0;
clkFrame_p = 1;
clkFrame_n = 0;
datain_n = 2'b11;
datain_p = 2'b00;
reset = 0;
end
//define ADC clock
always begin
#10 clkADC_p = ~clkADC_p;
clkADC_n = ~clkADC_n;
end
//define wall clock
always begin
#100 clkWall = ~clkWall;
end
//define LVDS bit rate clock
always begin
#1 clkin_p = ~clkin_p;
clkin_n = ~clkin_n;
end
//definte LVDS frame clock
always begin
#16 clkFrame_p = ~clkFrame_p;
clkFrame_n = ~clkFrame_n;
end
//define LVDS frame slip to test bitslip
always begin
#100 clkFrame_p = ~clkFrame_p;
clkFrame_n = ~clkFrame_n;
end
//define the LVDS datain test bit stream
always begin
#1 datain_p[0] = ~datain_p[0];
datain_n[0] = ~datain_n[0];
#1 datain_p[0] = ~datain_p[0];
datain_n[0] = ~datain_n[0];
datain_p[1] = ~datain_p[1];
datain_n[1] = ~datain_n[1];
end
always begin
#1000 $finish;
end
endmodule
The two modules serdes_1_to_n_data_ddr_s8_diff and serdes_1_to_n_clk_ddr_s8_diff are from the XAPP1064.
It compiles and simulates. My first question is what causes the delay in the startup of rxioclkp? It doesn't start for about 100 ps in simulation. Is this inherent to the IODELAY2 block?
My main question is why there is no data out. It seems as if rx_serdesstrobe and rx_bufg_x1 go low and stay low always and so does bslip. I've done some poking around but nothing jumps out at me but I'm sure I'm misunderstanding the functional blocks somehow (or how verilog works which is equally likely). This project would be a lot more tractable if there were someone in-house at my company that I could ask questions.
Thanks again for all of your help.
module main(
// input clocks for PLL
input wire clkADC_p,
input wire clkADC_n,
input wire clkWall,
// input LVDS bit rate clock
input wire clkin_p,
input wire clkin_n,
//input LVDS frame clock
input wire clkFrame_p,
input wire clkFrame_n,
//input LVDS data
input wire [1:0] datain_p,
input wire [1:0] datain_n,
//LVDS reset
input reset,
//output clock control for PLL
output wire vxcoCtrl,
//output wire div_clk,
//ouput deserialized data
output wire [15:0] dataout,
// Indicator that program was successful
output wire LEDIndicator);
// Begin main program
// ADC clock
wire clkADC;
wire div_clk;
// Divided down ADC clock by divisor
reg [25:0] divisor = 1382400;
parameter integer S = 8 ; // Set the serdes factor to 8
parameter integer C = 0 + 1; // Set the number of channels (increment by one for drive)
parameter integer D = 2*C ; // Set the number LVDS inputs = 2 * number of channels
parameter integer DS = (D*S)-1; // Used for bus widths = serdes factor * number of inputs - 1
wire [DS:0] rxd ; // Data from serdeses
wire [S-1:0] rxf ; // Recieved Data from Frame Clock
reg state ;
reg bslip ;
reg [3:0] count ;
assign rst = reset ; // active high reset pin
// turn on LED indicator to show successful programming
assign LEDIndicator = 1'b1;
// Configure differential PECL clock input
IBUFDS #(
.CAPACITANCE("DONT_CARE"),
.DIFF_TERM("FALSE"),
.IBUF_DELAY_VALUE("0"),
.IFD_DELAY_VALUE("AUTO"),
.IOSTANDARD("LVPECL_33"))
IBUFDS_inst1 (
.O(clkADC),
.I(clkADC_p),
.IB(clkADC_n));
// Perform clock divider
clk_divider clk_divider_inst (
.clk(clkADC),
.divisor(divisor),
.div_clk(div_clk));
// do PLL clock phase comparison
assign vxcoCtrl = div_clk ^ clkWall;
//Clock Input. Generate ioclocks via BUFIO2
serdes_1_to_n_clk_ddr_s8_diff #(
.S (S), // Set the serdes factor to 8
.DIFF_TERM ("TRUE")) // Enable or disable diff termination
inst_clkin (
.clkin_p (clkin_p),
.clkin_n (clkin_n),
.rxioclkp (rxioclkp),
.rxioclkn (rxioclkn),
.rx_serdesstrobe (rx_serdesstrobe),
.rx_bufg_x1 (rx_bufg_x1));
// Data Inputs
serdes_1_to_n_data_ddr_s8_diff #(
.S (S),
.D (D),
.DIFF_TERM ("TRUE")) // Enable or disable diff termination
inst_datain (
.use_phase_detector (1'b1), // '1' enables the phase detector logic
.datain_p (datain_p),
.datain_n (datain_n),
.rxioclkp (rxioclkp),
.rxioclkn (rxioclkn),
.rxserdesstrobe (rx_serdesstrobe),
.gclk (rx_bufg_x1),
.bitslip (bslip),
.reset (rst),
.data_out (rxd),
.debug_in (2'b00),
.debug ());
// Frame clock to use in logic of bitslip
// Data Inputs
serdes_1_to_n_data_ddr_s8_diff #(
.S (S),
.D (1),
.DIFF_TERM ("TRUE")) // Enable or disable diff termination
inst_frameclk (
.use_phase_detector (1'b1), // '1' enables the phase detector logic
.datain_p (clkFrame_p),
.datain_n (clkFrame_n),
.rxioclkp (rxioclkp),
.rxioclkn (rxioclkn),
.rxserdesstrobe (rx_serdesstrobe),
.gclk (rx_bufg_x1),
.bitslip (bslip),
.reset (rst),
.data_out (rxf),
.debug_in (2'b00),
.debug ());
always @ (posedge rx_bufg_x1 or posedge rst) // example bitslip logic, if required
begin
if (reset == 1'b1) begin
state <= 0 ;
bslip <= 1'b0 ;
count <= 4'b0000 ;
end
else begin
if (state == 0) begin
if (rxf[S-1:0] != 8'b00000000 & rxf[S-1:0] != 8'b11111111) begin
bslip <= 1'b1 ; // bitslip needed
state <= 1 ;
count <= 4'b0000 ;
end
end
else if (state == 1) begin
bslip <= 1'b0 ; // bitslip low
count <= count + 4'b0001 ;
if (count == 4'b1111) begin
state <= 0;
end
end
end
end
//output deserialized data
assign dataout = rxd;
endmodule
With the following test module:
module main_tb ();
// Inputs
reg clkADC_p; //ADC clock
reg clkADC_n;
reg clkWall; //60 Hz clock
reg clkin_p; //LVDS bit clock from ADC
reg clkin_n;
reg clkFrame_p; //LVDS frame clock from ADC
reg clkFrame_n;
reg [1:0] datain_p; //LVDS datain
reg [1:0] datain_n;
reg reset; //reset signal for LVDS deserialization block
// Outputs
wire vxcoCtrl; //Output control signal for the clock PLL
wire [15:0] dataout; //Deserialized data out
//wire div_clk;
wire LEDIndicator; //successful programming
// Instantiate the Unit Under Test (UUT)
main uut (
.clkADC_p(clkADC_p),
.clkADC_n(clkADC_n),
.clkWall(clkWall),
.clkin_p(clkin_p),
.clkin_n(clkin_n),
.clkFrame_p(clkFrame_p),
.clkFrame_n(clkFrame_n),
.datain_p(datain_p),
.datain_n(datain_n),
.reset(reset),
.vxcoCtrl(vxcoCtrl),
.dataout(dataout),
//.div_clk(div_clk),
.LEDIndicator(LEDIndicator)
);
initial begin
// Initialize Inputs
clkADC_p = 1;
clkADC_n = 0;
clkWall = 1;
clkin_p = 1;
clkin_n = 0;
clkFrame_p = 1;
clkFrame_n = 0;
datain_n = 2'b11;
datain_p = 2'b00;
reset = 0;
end
//define ADC clock
always begin
#10 clkADC_p = ~clkADC_p;
clkADC_n = ~clkADC_n;
end
//define wall clock
always begin
#100 clkWall = ~clkWall;
end
//define LVDS bit rate clock
always begin
#1 clkin_p = ~clkin_p;
clkin_n = ~clkin_n;
end
//definte LVDS frame clock
always begin
#16 clkFrame_p = ~clkFrame_p;
clkFrame_n = ~clkFrame_n;
end
//define LVDS frame slip to test bitslip
always begin
#100 clkFrame_p = ~clkFrame_p;
clkFrame_n = ~clkFrame_n;
end
//define the LVDS datain test bit stream
always begin
#1 datain_p[0] = ~datain_p[0];
datain_n[0] = ~datain_n[0];
#1 datain_p[0] = ~datain_p[0];
datain_n[0] = ~datain_n[0];
datain_p[1] = ~datain_p[1];
datain_n[1] = ~datain_n[1];
end
always begin
#1000 $finish;
end
endmodule
The two modules serdes_1_to_n_data_ddr_s8_diff and serdes_1_to_n_clk_ddr_s8_diff are from the XAPP1064.
It compiles and simulates. My first question is what causes the delay in the startup of rxioclkp? It doesn't start for about 100 ps in simulation. Is this inherent to the IODELAY2 block?
My main question is why there is no data out. It seems as if rx_serdesstrobe and rx_bufg_x1 go low and stay low always and so does bslip. I've done some poking around but nothing jumps out at me but I'm sure I'm misunderstanding the functional blocks somehow (or how verilog works which is equally likely). This project would be a lot more tractable if there were someone in-house at my company that I could ask questions.
Thanks again for all of your help.