1
votes

I understand when using case syntax in systemverilog, we need to fully describe all combinations or add a default to avoid latches.

Here is my example code, no latches are generated:

 module test(
input logic[2:0] op,
output logic a,b,c
);

    always_comb
    begin

    case(op)

     0: {a,b,c} = {1'b1,1'b1,1'b0};
     1: {a,b,c} = {1'b1,1'b0,1'b0};
     2: {a,b,c} = {1'b0,1'b1,1'b0};
     default: {a,b,c} = {1'b0,1'b0,1'b0};
     endcase
     end
     endmodule

As I said in the beginning, if add a default, not latches are generated. Please look the second code, which is a ALU design:

module ALU(
output logic[31:0] Result,
output logic Zero, Overflow, Negative, Carryout,

input logic [5:0]ALUOp_i,
input logic [31:0] ALU_A_i, ALU_B_i,
input logic [4:0] Shamt
);

logic [31:0] adder_b;

always_comb
begin


  casez(ALUOp_i)

 /*Add_trap*/   0,1: {Carryout,Result} = {ALU_A_i[31],ALU_A_i} + {ALU_B_i[31],ALU_B_i};
 /*Add_notrap*/ 
 /*Subtrap*/    2,3: 
 /*Sub_notrap*/    begin
             adder_b = ALU_B_i ^ {32{1'b1}};
             {Carryout,Result} = {ALU_A_i[31],ALU_A_i} + {adder_b[31],adder_b} + 1;
           end

/*SLL*/         8: Result = ALU_B_i << Shamt;
/*SLLV*/        9: Result = ALU_B_i << ALU_A_i;
/*SRA*/         10: Result = ALU_B_i >>> Shamt;
/*SRAV*/        11: Result = ALU_B_i >>> ALU_A_i;
/*SRL*/         12: Result = ALU_B_i >> Shamt;
/*SRLV*/        13: Result = ALU_B_i >> ALU_A_i;
/*AND*/         14: Result = ALU_A_i && ALU_B_i;
/*OR*/          15: Result = ALU_A_i || ALU_B_i;
/*XOR*/         16: Result = ALU_A_i ^^ ALU_B_i;
                default:
          begin
               Result = 0;
               Carryout = 0;
               adder_b = 0;
          end        
  endcase
end
endmodule   

The code above will generated latches, here is the result given by Quartus II:

Warning (10240): Verilog HDL Always Construct warning at ALU.sv(16): inferring latch(es) for variable "Carryout", which holds its previous value in one or more paths through the always construct

Warning (10240): Verilog HDL Always Construct warning at ALU.sv(16): inferring latch(es) for variable "adder_b", which holds its previous value in one or more paths through the always construct

Error (10166): SystemVerilog RTL Coding error at ALU.sv(16): always_comb construct does not infer purely combinational logic.

I did added a default in the end of the case, can some one explain what is going on? Many thanks.

2
One code suggestion: Why not do a subtraction instead of manually trying to negate ALU_B_i? Your synthesis tool should be able to figure out how to do a subtract operation.nguthrie
Yes, your correct. My first ALU design exercise used that code, and its worked fine, so I just copy and paste that code in every ALU I designed afterwards.Shuaiyu Jiang

2 Answers

5
votes

The clean and easy solution here is to assign a default value Carryout at the beginning of the always_comb block. The last assignment will win, so any branch that does not assign a value to Carryout will get the default value.

A simple example of how the last assignment wins is shown below:

always_comb begin
   Carryout = 1'b0;
   if(some_condition) begin
      Carryout = 1'b1;
   end
end

In the above code Carryout is assigned to 0, and then if some_condition is true it is reassigned to 1. If some_condition is false, then it just keeps the "default" value of 0. This all happens in the same time step, so there is not transient glitch on the output.

1
votes

While you are correct about multiple paths through a case statement (and needing a default clause), latches are also generated if a signal isn't present in every branch. In this case, Carryout and adder_b are only present in some of the paths. As a result, your synthesis tool assumes you want the values to be stored, which generates a latch.

You'll need to assign some value to those signals in every branch of the case. For example:

/*SLL*/         8: begin
                      Result = ALU_B_i << Shamt;
                      ader_b = 0;
                      Carryout = 0;
                end

Repeat for the other branches.