Xilinx warnings (FF/Latch trimming) in Verilog for

2019-06-14 14:57发布

问题:

In this other question I asked I got some general advice regarding my module. Now I seek advice here since I noted that the Verilog community has more users.

I am trying to implement into an existing framework a Most Significant Bit (MSB) operation. The idea is as follows: I am getting 32 bit complex samples in from ddc_out_strobe, which are 16 bit I and 16 bit Q. My idea is to combine 4 "cutted" samples into a new sample to feed to the output bb_sample. This is done by getting the 4 MSB out of I0,Q0,I1,Q1,I2,Q2,I3,Q3 (4*8 = 32 bit total) and wiring them every 4th bb_strobe to bb_sample.

Here you can see my implementation:

module my_rx_dsp0_custom
#(
    //frontend bus width
    parameter WIDTH = 24
)
(
    //control signals
    input clock, //dsp clock
    input reset, //active high synchronous reset
    input clear, //active high on packet control init
    input enable, //active high when streaming enabled

    //user settings bus, controlled through user setting regs API
    input set_stb, input [7:0] set_addr, input [31:0] set_data,

    //full rate inputs directly from the RX frontend
    input [WIDTH-1:0] frontend_i,
    input [WIDTH-1:0] frontend_q,

    //full rate outputs directly to the DDC chain
    output [WIDTH-1:0] ddc_in_i,
    output [WIDTH-1:0] ddc_in_q,

    //strobed samples {I16,Q16} from the RX DDC chain
    input [31:0] ddc_out_sample,
    input ddc_out_strobe, //high on valid sample
    output ddc_out_enable, //enables DDC module

    //strobbed baseband samples {I16,Q16} from this module
    output [31:0] bb_sample,
    output bb_strobe //high on valid sample
);

    reg [3:0] i_msb;
    reg [3:0] q_msb;

    reg [31:0]temp_buff = 0;
    reg [31:0]my_zeros = 0;
    reg [1:0] count = 0;

    always @(posedge clock) 
        if(ddc_out_strobe) begin
            i_msb <= ddc_out_sample[31:28];
            q_msb <= ddc_out_sample[15:12];
            temp_buff <= {i_msb,q_msb,temp_buff[31:24]};
            // to avoid if-else conditions
            count <= (count==2'd3) ? 2'd0 : (count+1);
        end

    // to avoid if-else conditions
    assign bb_strobe = (count==2'd3) ? 1'b1 : 1'b0; 

    assign bb_sample = (count==2'd3) ? temp_buff : my_zeros;    
    assign ddc_out_enable = enable;
    assign ddc_in_i = frontend_i;
    assign ddc_in_q = frontend_q;   

endmodule //my_rx_dsp0_custom

(1) When trying to build the FPGA images I get the following warning (I just show you the one for 23, but it is the same for other ones):

WARNING:Xst:1896 - Due to other FF/Latch trimming, FF/Latch <temp_buff_23> has a constant value of 0 in block <my_rx_dsp0_custom>. This FF/Latch will be trimmed during the optimization process

I have searched this problem in SE and found some good explanations on what might be going wrong, here or here for example. What I understand is the following: temp_buff <= {i_msb,q_msb,temp_buff[31:24]}; is a conflictive line since the <= operator is getting the old values from i_msb and q_msb, and not the ones from the MSB operation.

(2) I tried avoiding if-else conditions to allow me to declare some things out of the always @* block (this way I avoid having a wire on the LHS of an always block, which is not allowed).

Are my conditionals correct? As I explained before, I want only every 4th bb_sample to be assigned. Is assign bb_strobe = (count==2'd3) ? 1'b1 : 1'b0; getting the effect I want despite not being in the always @(posedge clock) block?

If other infos are needed, please let me know. This is part of a much bigger project that I am trying to modify for my purposes.

回答1:

(1) The trimmed FF/Latch warning is not due to non-blocking assignments. It is from 24 bits of the temp_buff register always being assigned to zeros. The RHS is 16bits; i_msb (4 bits), q_msb (4 bits), and temp_buff[31:24] (8 bits). And you are assigning it to a 32bit value. The assignment:

temp_buff <= {i_msb,q_msb,temp_buff[31:24]};

Is equivalent to:

temp_buff <= {16'h0000, i_msb,q_msb,temp_buff[31:24]};

This means temp_buff[31:16] will always be zero can can be optimized out. temp_buff[7:0] can also be optimized out to constant zeros because it is assigned to temp_buff[31:24] which is a constant 0. Perhaps you meant you shift right 8 bits like so:

temp_buff <= {i_msb,q_msb,temp_buff[31: 8 ]};

(2) You are correct that wires should not be assigned with any always block (or initial block). However you could have turned the wire to a reg. It is a miss conception that reg is for registers only (FF/Latches). reg in a properly coded combinational block will create combinational logic (no FF or Latches). Property meaning the reg is assigned within every branching condition withing the always block, else it infers a latch. Example

module my_rx_dsp0_custom
/* ... your original code ... */
    output reg [31:0] bb_sample,
    output reg bb_strobe //high on valid sample
);
/* ... your original code ... */
    always @(posedge clock) 
        if(ddc_out_strobe) begin
            temp_buff <= {i_msb,q_msb,temp_buff[31:8]};
            count <= (count==2'd3) ? 2'd0 : (count+1);
        end

    always @*
        begin
            i_msb = ddc_out_sample[31:28];
            q_msb = ddc_out_sample[15:12];
            bb_strobe = (count==2'd3); 
            bb_sample = bb_strobe ? temp_buff : 32'd0;  
        end

    assign ddc_out_enable = enable;
/* ... your original code ... */