Search code examples
veriloghdl

Verilog Temporary Variable


I tried to make a CMP instruction in Verilog. To keep the result of the substraction, I declared a wire. This is what the code looks like (It is executed in an always statement).

wire [data_width:0] tmp_wire = reg_accumulator - reg_x;

f_zero <= tmp_wire & 'hFF == 0;
f_carry <= tmp_wire & 'h100;

Now Icarus Verilog complains about a syntax error and that reg_accumulator - reg_x is not an l-value:

cpu.v:149: syntax error
cpu.v:149: Syntax in assignment statement l-value.

And why does it complain? What would be the right approach to declare a temporary variable in a function / task?

module comparator(
    input clk,
    input [7:0] op_a,
    input [7:0] op_b
);

reg f_zero;
reg f_carry;

function compare;
    input [data_width-1:0] a;
    input [data_width-1:0] b;
begin
    wire [7:0] tmp_wire = reg_accumulator - reg_x;

    f_zero <= tmp_wire & 'hFF == 0;
    f_carry <= tmp_wire & 'h100;
end
endfunction

always @(posedge clk) begin
    compare(op_a, op_b);
end

endmodule // comparator

Solution

  • Either you should use systemverilog and include this in a class or you can create a parameterized module:

    module compare_zero_n_carry
    # (
        parameter DATA_WIDTH = 8
      )
    (zero, carry, a, b);
    
      /* ports */
      input [DATA_WIDTH-1:0] a;  //.."reg_accumulator"
      input [DATA_WIDTH-1:0] b;  //.."reg_x"
      output zero;
      output carry;
    
      wire [DATA_WIDTH-1:0] tmp_wire = a - b;
    
      assign zero = (tmp_wire & {DATA_WIDTH{1'b1}}) == {DATA_WIDTH{1'b0}};
      //..HERE IM NOT REALLY SURE WHAT IS THE LOGIC FOR THE CARRY,
      //..IT SHOULD BE ONE BIT
      assign carry = (tmp_wire & {1'b1,{(DATA_WIDTH-1){1'b0}}});     
    endmodule // compare_zero_n_carry
    

    And instantiate it in the main comparator module as:

      input                   clk;
      input [DATA_WIDTH-1:0]  op_a;
      input [DATA_WIDTH-1:0]  op_b;
    
      wire f_zero;
      wire f_carry;
      reg f_zero_reg;
      reg f_carry_reg;
    
      compare_zero_n_carry
        # (
            .DATA_WIDTH (DATA_WIDTH)
          )
        compare_zero_n_carry_inst (
            .a      (op_a),
            .b      (op_b),
            .zero   (f_zero),
            .carry  (f_carry)
          );
    
      always @ (posedge clk) begin
        f_zero_reg <= f_zero;
        f_carry_reg <= f_carry;
      end