1

我有以下 Verilog 代码:

//////////////////////////////////////////////////////////////////////////////
//
//  Xilinx, Inc. 2010                 www.xilinx.com
//
//  XAPP xxx - 1:5 Differential Data De-serializer
//
//////////////////////////////////////////////////////////////////////////////
//
//  File name :       serdes_1_to_5_diff_data.v
//
//  Description :     This module instantiates IODELAY2 and ISERDES2 primitives
//                    to receive TMDS differential data in 1:5 format
//
//  Note:             
//
//  Author :    Bob Feng 
//////////////////////////////////////////////////////////////////////////////
//
//  Disclaimer: 
//
//    This disclaimer is not a license and does not grant any rights to the materials 
//    distributed herewith. Except as otherwise provided in a valid license issued to you 
//    by Xilinx, and to the maximum extent permitted by applicable law: 
//    (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL FAULTS, 
//    AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, 
//    INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, OR 
//    FITNESS FOR ANY PARTICULAR PURPOSE; and (2) Xilinx shall not be liable (whether in contract 
//    or tort, including negligence, or under any other theory of liability) for any loss or damage 
//    of any kind or nature related to, arising under or in connection with these materials, 
//    including for any direct, or any indirect, special, incidental, or consequential loss 
//    or damage (including loss of data, profits, goodwill, or any type of loss or damage suffered 
//    as a result of any action brought by a third party) even if such damage or loss was 
//    reasonably foreseeable or Xilinx had been advised of the possibility of the same.
//
//  Critical Applications:
//
//    Xilinx products are not designed or intended to be fail-safe, or for use in any application 
//    requiring fail-safe performance, such as life-support or safety devices or systems, 
//    Class III medical devices, nuclear facilities, applications related to the deployment of airbags,
//    or any other applications that could lead to death, personal injury, or severe property or 
//    environmental damage (individually and collectively, "Critical Applications"). Customer assumes 
//    the sole risk and liability of any use of Xilinx products in Critical Applications, subject only 
//    to applicable laws and regulations governing limitations on product liability.
//
//  THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE AT ALL TIMES.
//
//////////////////////////////////////////////////////////////////////////////

`timescale 1ps/1ps

module serdes_1_to_5_diff_data # (
  parameter DIFF_TERM = "TRUE",
  parameter SIM_TAP_DELAY = 49,
  parameter BITSLIP_ENABLE = "FALSE"
)(
  input  wire        use_phase_detector,  // '1' enables the phase detector logic
  input  wire        datain_p,            // Input from LVDS receiver pin
  input  wire        datain_n,            // Input from LVDS receiver pin
  input  wire        rxioclk,             // IO Clock network
  input  wire        rxserdesstrobe,      // Parallel data capture strobe
  input  wire        reset,               // Reset line
  input  wire        gclk,                // Global clock
  input  wire        bitslip,             // Bitslip control line
  output wire [4:0]  data_out             // Output data
);  

  wire       ddly_m;
  wire       ddly_s;
  wire       busys;
  wire       rx_data_in;
  wire       cascade;
  wire       pd_edge;
  reg  [8:0] counter;
  reg  [3:0] state;
  reg        cal_data_sint;
  wire       busy_data;
  reg        busy_data_d;
  wire       cal_data_slave;
  reg        enable;
  reg        cal_data_master;
  reg        rst_data;
  reg        inc_data_int;   //THIS LINE (81) IS CAUSING THE ERROR
  wire       inc_data;
  reg        ce_data;
  reg        valid_data_d;
  reg        incdec_data_d;
  reg  [4:0] pdcounter;
  wire       valid_data;
  wire       incdec_data;
  reg        flag;
  reg        mux;
  reg        ce_data_inta ;
  wire [1:0] incdec_data_or;
  wire       incdec_data_im;
  wire [1:0] valid_data_or;
  wire       valid_data_im;
  wire [1:0] busy_data_or;
  wire       all_ce;

  wire [1:0] debug_in = 2'b00;

  assign busy_data = busys ;

  assign cal_data_slave = cal_data_sint ;

  /////////////////////////////////////////////////
  //
  // IDELAY Calibration FSM
  //
  /////////////////////////////////////////////////
  always @ (posedge gclk or posedge reset)
  begin
  if (reset == 1'b1) begin
    state <= 0 ;
    cal_data_master <= 1'b0 ;
    cal_data_sint <= 1'b0 ;
    counter <= 9'h000 ;
    enable <= 1'b0 ;
    mux <= 1'h1 ;
  end
  else begin
      counter <= counter + 9'h001 ;
      if (counter[8] == 1'b1) begin
      counter <= 9'h000 ;
      end
      if (counter[5] == 1'b1) begin
      enable <= 1'b1 ;
      end
      if (state == 0 && enable == 1'b1) begin       // Wait for IODELAY to be available
      cal_data_master <= 1'b0 ;
      cal_data_sint <= 1'b0 ;
      rst_data <= 1'b0 ;
        if (busy_data_d == 1'b0) begin
        state <= 1 ;
      end
      end
      else if (state == 1) begin          // Issue calibrate command to both master and slave, needed for simulation, not for the silicon
        cal_data_master <= 1'b1 ;
        cal_data_sint <= 1'b1 ;
        if (busy_data_d == 1'b1) begin        // and wait for command to be accepted
          state <= 2 ;
        end
      end
      else if (state == 2) begin          // Now RST master and slave IODELAYs needed for simulation, not for the silicon
        cal_data_master <= 1'b0 ;
        cal_data_sint <= 1'b0 ;
        if (busy_data_d == 1'b0) begin
          rst_data <= 1'b1 ;
          state <= 3 ;
        end
      end
      else if (state == 3) begin          // Wait for IODELAY to be available
        rst_data <= 1'b0 ;
        if (busy_data_d == 1'b0) begin
          state <= 4 ;
        end
      end
      else if (state == 4) begin          // Wait for occasional enable
        if (counter[8] == 1'b1) begin
          state <= 5 ;
        end
        end
        else if (state == 5) begin          // Calibrate slave only
        if (busy_data_d == 1'b0) begin
          cal_data_sint <= 1'b1 ;
          state <= 6 ;
        end
      end
        else if (state == 6) begin          // Wait for command to be accepted
        cal_data_sint <= 1'b0 ;
        if (busy_data_d == 1'b1) begin
          state <= 7 ;
        end
      end
      else if (state == 7) begin          // Wait for all IODELAYs to be available, ie CAL command finished
          cal_data_sint <= 1'b0 ;
        if (busy_data_d == 1'b0) begin
          state <= 4 ;
        end
      end
  end
  end

always @ (posedge gclk or posedge reset)        // Per-bit phase detection state machine
begin
if (reset == 1'b1) begin
  pdcounter <= 5'b1000 ;
  ce_data_inta <= 1'b0 ;
  flag <= 1'b0 ;              // flag is there to only allow one inc or dec per cal (test)
end
else begin
  busy_data_d <= busy_data_or[1] ;
    if (use_phase_detector == 1'b1) begin       // decide whther pd is used
    incdec_data_d <= incdec_data_or[1] ;
    valid_data_d <= valid_data_or[1] ;
    if (ce_data_inta == 1'b1) begin
      ce_data = mux ;
    end
    else begin
      ce_data = 64'h0000000000000000 ;
    end
      if (state == 7) begin
      flag <= 1'b0 ;
    end
      else if (state != 4 || busy_data_d == 1'b1) begin // Reset filter if state machine issues a cal command or unit is busy
      pdcounter <= 5'b10000 ;
        ce_data_inta <= 1'b0 ;
      end
      else if (pdcounter == 5'b11111 && flag == 1'b0) begin // Filter has reached positive max - increment the tap count
        ce_data_inta <= 1'b1 ;
        inc_data_int <= 1'b1 ;
      pdcounter <= 5'b10000 ;
      flag <= 1'b1 ;
    end
        else if (pdcounter == 5'b00000 && flag == 1'b0) begin // Filter has reached negative max - decrement the tap count
        ce_data_inta <= 1'b1 ;
        inc_data_int <= 1'b0 ;
      pdcounter <= 5'b10000 ;
      flag <= 1'b1 ;
      end
    else if (valid_data_d == 1'b1) begin      // increment filter
        ce_data_inta <= 1'b0 ;
      if (incdec_data_d == 1'b1 && pdcounter != 5'b11111) begin
        pdcounter <= pdcounter + 5'b00001 ;
      end
      else if (incdec_data_d == 1'b0 && pdcounter != 5'b00000) begin  // decrement filter
        pdcounter <= pdcounter + 5'b11111 ;
      end
      end
      else begin
        ce_data_inta <= 1'b0 ;
      end
    end
    else begin
    ce_data = all_ce ;
    inc_data_int = debug_in[1] ;
    end
end
end

assign inc_data = inc_data_int ;

assign incdec_data_or[0] = 1'b0 ;             // Input Mux - Initialise generate loop OR gates
assign valid_data_or[0] = 1'b0 ;
assign busy_data_or[0] = 1'b0 ;

assign incdec_data_im = incdec_data & mux;          // Input muxes
assign incdec_data_or[1] = incdec_data_im | incdec_data_or;      // AND gates to allow just one signal through at a tome
assign valid_data_im = valid_data & mux;          // followed by an OR
assign valid_data_or[1] = valid_data_im | valid_data_or;     // for the three inputs from each PD
assign busy_data_or[1] = busy_data | busy_data_or;       // The busy signals just need an OR gate

assign all_ce = debug_in[0] ;

IBUFDS #(
  .DIFF_TERM    (DIFF_TERM)) 
data_in (
  .I            (datain_p),
  .IB           (datain_n),
  .O            (rx_data_in)
);

//
// Master IDELAY
//
IODELAY2 #(
  .DATA_RATE            ("SDR"),
  .IDELAY_VALUE         (0),
  .IDELAY2_VALUE        (0),
  .IDELAY_MODE          ("NORMAL" ),
  .ODELAY_VALUE         (0),
  .IDELAY_TYPE          ("DIFF_PHASE_DETECTOR"),
  .COUNTER_WRAPAROUND   ("STAY_AT_LIMIT"), //("WRAPAROUND"),
  .DELAY_SRC            ("IDATAIN"),
  .SERDES_MODE          ("MASTER"),
  .SIM_TAPDELAY_VALUE   (SIM_TAP_DELAY)
) iodelay_m (
  .IDATAIN              (rx_data_in),      // data from IBUFDS
  .TOUT                 (),                // tri-state signal to IOB
  .DOUT                 (),                // output data to IOB
  .T                    (1'b1),            // tri-state control from OLOGIC/OSERDES2
  .ODATAIN              (1'b0),            // data from OLOGIC/OSERDES2
  .DATAOUT              (ddly_m),          // Output data 1 to ILOGIC/ISERDES2
  .DATAOUT2             (),                // Output data 2 to ILOGIC/ISERDES2
  .IOCLK0               (rxioclk),         // High speed clock for calibration
  .IOCLK1               (1'b0),            // High speed clock for calibration
  .CLK                  (gclk),            // Fabric clock (GCLK) for control signals
  .CAL                  (cal_data_master), // Calibrate control signal
  .INC                  (inc_data),        // Increment counter
  .CE                   (ce_data),         // Clock Enable
  .RST                  (rst_data),        // Reset delay line
  .BUSY                 ()                 // output signal indicating sync circuit has finished / calibration has finished
);

//
// Slave IDELAY
//
IODELAY2 #(
  .DATA_RATE            ("SDR"),
  .IDELAY_VALUE         (0),
  .IDELAY2_VALUE        (0),
  .IDELAY_MODE          ("NORMAL" ),
  .ODELAY_VALUE         (0),
  .IDELAY_TYPE          ("DIFF_PHASE_DETECTOR"),
  .COUNTER_WRAPAROUND   ("WRAPAROUND"),
  .DELAY_SRC            ("IDATAIN"),
  .SERDES_MODE          ("SLAVE"),
  .SIM_TAPDELAY_VALUE   (SIM_TAP_DELAY)
) iodelay_s (
  .IDATAIN              (rx_data_in),  // data from IBUFDS
  .TOUT                 (),            // tri-state signal to IOB
  .DOUT                 (),            // output data to IOB
  .T                    (1'b1),        // tri-state control from OLOGIC/OSERDES2
  .ODATAIN              (1'b0),        // data from OLOGIC/OSERDES2
  .DATAOUT              (ddly_s),      // Slave output data to ILOGIC/ISERDES2
  .DATAOUT2             (),            //
  .IOCLK0               (rxioclk),     // High speed IO clock for calibration
  .IOCLK1               (1'b0),
  .CLK                  (gclk),        // Fabric clock (GCLK) for control signals
  .CAL                  (cal_data_slave), // Calibrate control signal
  .INC                  (inc_data),       // Increment counter
  .CE                   (ce_data),        // Clock Enable
  .RST                  (rst_data),       // Reset delay line
  .BUSY                 (busys)        // output signal indicating sync circuit has finished / calibration has finished
);

//
// Master ISERDES
//

ISERDES2 #(
  .DATA_WIDTH       (5),
  .DATA_RATE        ("SDR"),
  .BITSLIP_ENABLE   (BITSLIP_ENABLE),
  .SERDES_MODE      ("MASTER"),
  .INTERFACE_TYPE   ("RETIMED"))
iserdes_m (
  .D                (ddly_m),
  .CE0              (1'b1),
  .CLK0             (rxioclk),
  .CLK1             (1'b0),
  .IOCE             (rxserdesstrobe),
  .RST              (reset),
  .CLKDIV           (gclk),
  .SHIFTIN          (pd_edge),
  .BITSLIP          (bitslip),
  .FABRICOUT        (),
  .Q4               (data_out[4]),
  .Q3               (data_out[3]),
  .Q2               (data_out[2]),
  .Q1               (data_out[1]),
  .DFB              (),
  .CFB0             (),
  .CFB1             (),
  .VALID            (valid_data),
  .INCDEC           (incdec_data),
  .SHIFTOUT         (cascade));

//
// Slave ISERDES
//

ISERDES2 #(
  .DATA_WIDTH       (5),
  .DATA_RATE        ("SDR"),
  .BITSLIP_ENABLE   (BITSLIP_ENABLE),
  .SERDES_MODE      ("SLAVE"),
  .INTERFACE_TYPE   ("RETIMED")
) iserdes_s (
  .D                (ddly_s),
  .CE0              (1'b1),
  .CLK0             (rxioclk),
  .CLK1             (1'b0),
  .IOCE             (rxserdesstrobe),
  .RST              (reset),
  .CLKDIV           (gclk),
  .SHIFTIN          (cascade),
  .BITSLIP          (bitslip),
  .FABRICOUT        (),
  .Q4               (data_out[0]),
  .Q3               (),
  .Q2               (),
  .Q1               (),
  .DFB              (),
  .CFB0             (),
  .CFB1             (),
  .VALID            (),
  .INCDEC           (),
  .SHIFTOUT         (pd_edge));


reg [7:0] rxpdcntr = 8'h7f;
always @ (posedge gclk or posedge reset) begin
  if (reset)
    rxpdcntr <= 8'h7f;
  else if (ce_data)
    if (inc_data)
      rxpdcntr <= rxpdcntr + 1'b1;
    else
      rxpdcntr <= rxpdcntr - 1'b1;
end

endmodule

当我尝试在 Xilinx Platform Studio 中为此设计生成网表时,我不断收到以下错误:

ERROR:HDLCompiler:1511 - "/home/eamorr/Desktop/Dropbox/UCD/digitalEye/Atlys_HDMI_PLB_demo/project/pcores/hdmi_in_v1_00_a/hdl/verilog/serdes_1_to_5_diff_data.v" Line 82: Mix of blocking and non-blocking assignments to variable <inc_data_int> is not a recommended coding practice.
ERROR:EDK:546 - Aborting XST flow execution!
ERROR:EDK:440 - platgen failed with errors!
make: *** [implementation/system_microblaze_0_wrapper.ngc] Error 2

我完全被卡住了,不知道该怎么办。

4

2 回答 2

3

为了推断综合的时序逻辑,您应该使用nonblockingassignments ( <=) 而不是blockingassignments ( =)。例如,更改:

  ce_data = mux ;

到:

  ce_data <= mux ;
于 2013-01-23T16:33:34.460 回答
0

那来自我假设的digilentic网站上的HDMI示例。

查看所有 inc_data_int 分配:

inc_data_int <= 1'b1 ;
inc_data_int <= 1'b0 ;
inc_data_int = debug_in[1] ;

我会注释掉最后一个,因为我认为它是出于调试目的。

(我让 HDMI 像那样工作。)

于 2013-05-07T13:57:20.480 回答