mrpp
mrpp

Reputation: 31

Why does this code always generate latches?

module OB_Addr_Contr_B1(
    input                       clk,
    input                       rst_n,
    input  wire signed [3:0]    o_00,
    output  reg     [31:0]      OB_Data_00,
                          
                                
    output  wire    [7:0]       addr_write_0,
    output  wire                write_enable_0      
);
    reg     [3:0]   cnt_0;
    reg     [5:0]   Data_cnt_00;
    reg             rom_enable_0;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_0 <= 0;
            Data_cnt_00 <= 0;
        end
        else if(cnt_0 == 8) begin
            cnt_0 <= 1 ;
            Data_cnt_00 <= Data_cnt_00 + 1;
        end
        else begin
            cnt_0 <= cnt_0 + 1;
        end      
    end
    
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            rom_enable_0 <= 0;
        end
        else if(cnt_0 == 7)
            rom_enable_0 <= 1;
        else
            rom_enable_0 <= 0;
    
    end

    always@(*)begin
        if(cnt_0 == 0)
            OB_Data_00 = 0;
        else if(cnt_0<=8)begin
            OB_Data_00[31 - ((cnt_0-1'b1)<<2) -: 4] = o_00;
        end
        else
            OB_Data_00 = OB_Data_00;
    end

endmodule

My cnt_0 loops between 1~8, the always@(*) statement has covered all cases, but the hardware synthesized by Vivado will still generate "RTL_LATCH".

enter image description here

Changing "always@(*)" to "always@(posedge clk)" does generate registers instead of "RTL_LATCH", but this gives me problems with my waveforms because it delays the assignment by one clk, which makes me very distressed.

I uploaded 3 pictures. The first one above is the circuit diagram synthesized by the code I provided.

The first one below is the waveform diagram corresponding to the circuit diagram, the waveform is what I want, and it is correct when cnt_0 is 8 The output is "0xffffffff".

The waveform diagram below is a wrong waveform diagram. It is the waveform generated by changing "always@(*)" to "always@(posedge clk)". The delay of one cycle leads to the error of the result(0xfffffff0).

enter image description here enter image description here

I changed "always@(*)" to "always@(posedge clk)" and it did generate the circuit without LATCH, but also caused the waveform result to go from correct to wrong.

always@(cnt_0)begin
        case(cnt_0)
            0: OB_Data_00 = 0;
            1: OB_Data_00[31:28] = o_00;
            2: OB_Data_00[27:24] = o_00;
            3: OB_Data_00[23:20] = o_00;
            4: OB_Data_00[19:16] = o_00;
            5: OB_Data_00[15:12] = o_00;
            6: OB_Data_00[11: 8] = o_00;
            7: OB_Data_00[ 7: 4] = o_00;
            8: OB_Data_00[ 3: 0] = o_00;
            default:OB_Data_00 = 0;
        endcase
    end  

I modified the codes as suggested above and they still generate LATCH. enter image description here

Upvotes: 1

Views: 126

Answers (1)

toolic
toolic

Reputation: 62236

This line might be a cause for the inferred latch because it retains the state of OB_Data_00:

        OB_Data_00 = OB_Data_00;

You can probably simplify the always block as follows since cout_0 can never be greater than 8:

always @(*) begin
    if (cnt_0 == 0)
        OB_Data_00 = 0;
    else
        OB_Data_00[31 - ((cnt_0-1'b1)<<2) -: 4] = o_00;
end

the always@(*) statement has covered all cases

That statement is incorrect. This line is also a potential cause of inferred latches because it does not make an assignment to all 32 bits of OB_Data_00:

        OB_Data_00[31 - ((cnt_0-1'b1)<<2) -: 4] = o_00;

For example, when cnt_0=2, it resolves to:

        OB_Data_00[27:24] = o_00;

This only assigns to 4 of the 32 bits of OB_Data_00, leaving the other 28 bits to retain their state.

The case version of your code infers latches for the same reason. The case version has another problem: an incomplete sensitivity list. It should use always @*

Upvotes: 1

Related Questions