Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
7 years ago

newbie question: synchronous versus combinational bus mux using case statement

Hello all-

Can anyone explain why the first (synchronous) version below compiles in quartus, but the second (combinational) does not? In the 2nd case the error is:

Error (10137): Verilog HDL Procedural Assignment error at my_first_fpga.v(26): object "LED" on left-hand side of assignment must have a variable data type

Error (10137): Verilog HDL Procedural Assignment error at my_first_fpga.v(27): object "LED" on left-hand side of assignment must have a variable data type

Is there a proper way to code a combinational bus mux using a case statement?

Thanks

-J


module my_first_fpga    ( input     wire            CLOCK_50,
                          input     wire        KEY,
                          output     reg            LED
                        );
                        
    reg            count;
           
    always @ (posedge CLOCK_50)
    begin    
        count <= count + 1;
        case(KEY)
        0    :    LED = count;
        1    :    LED = count;
        endcase
    end  
endmodule


module my_first_fpga    ( input     wire            CLOCK_50,
                          input     wire        KEY,
                          output     wire        LED
                        );
                        
    reg            count;
    
    always @ (posedge CLOCK_50)
    begin    
        count <= count + 1;
    end
    
    always @ (KEY, count)
    case(KEY)
    0    :    LED = count;
    1    :    LED = count;
    endcase
    
endmodule

7 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    make LED a reg in 2nd code.

    A reg is not automatically a register, it is just a data type. A wire can only be used in an assign statement. reg types can be used in procedural code.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Or set Verilog HDL input to System Verilog, it will accept wire as assignment target.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    make LED a reg in 2nd code.

    A reg is not automatically a register, it is just a data type. A wire can only be used in an assign statement. reg types can be used in procedural code.

    --- Quote End ---

    Hi, thanks for the reply.

    So, it sounds like you are suggesting that a reg type can be used to generate combinational logic... say by using it outside of an always @ (posedge) block. I hadn't thought of this, but I'll give it a try and see if it works.

    -J
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    This is a quirk of Verilog. Reg is just a data type in the Verilog. What it maps to in logic is down to the behaviour in the code. It is just unfortunate they chose the name "reg"

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    This is a quirk of Verilog. Reg is just a data type in the Verilog. What it maps to in logic is down to the behavior in the code. It is just unfortunate they chose the name "reg"

    --- Quote End ---

    Yes, indeed, sir. I found both the code snippets below generate the desired combinational logic. I would guess the 2nd one might be frowned upon.

    Would you be able to recommend a book that covers these sorts of issues? It would be nice to find one that is written in Verilog 2001.

    Thanks again,

    -J

    
        always @ (KEY,count)
        case(KEY)
        0    :    LED = count;
        1    :    LED = count;
        endcase
    

        always @ (KEY)
        case(KEY)
        0    :    LED = count;
        1    :    LED = count;
        endcase
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The second code wont match between simulation and synthesis as you dont have count in the sensitivity list.

    Also, I recommend using non-blocking assignments in always blocks <=
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    The second code wont match between simulation and synthesis as you dont have count in the sensitivity list.

    Also, I recommend using non-blocking assignments in always blocks <=

    --- Quote End ---

    The first statement I agree with. Not so the second; it depends on what you are trying to accomplish.

    If you are trying to model physical registers, than using the non-blocking assignment <= makes sense, as it evaluates the right side, and then assigns the result to the left side based on the event used in the enclosing always block (typically 'posedge clk').

    If you want to model pure combinatorial logic and use 'reg' variables as intermediate holding values, with no intercycle memory, then blocking = assignment makes more sense, as it works within the procedural flow. Example:

    begin : label
          reg tmp;
          tmp = a;
          if (b == c) tmp = d;
          if (e == f) tmp = g;
          h = tmp;
    end

    produces the same result as:

    h = (e == f) ? g : ((b == c) ? d : a);

    Of course this is a very contrived example but sometimes it is more clear to write out the combinatorial logic as a multi line procedure rather than to combine the whole thing into a single equation.