0
votes

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
2
Assignments in an always block should be to regs (as you rightfully declared f_zero and f_carry). You put the wire declaration and assignment inside the always so the error is for trying to update a wire in an always block which is illegal... - Tomerikoo
@Tomerikoo Ok, but how can I declare something like a temporary variable? - sb27
Just like any other wire... You have the answer below. By the way, reg_accumulator and reg_x are not defined... - Tomerikoo
How should I declare a wire in a function with it's parameters? This is not going to work: function compare; input [data_width-1:0] a; input [data_width-1:0] b; wire [data_width:0] tmp = a - b; begin end endfunction - sb27
You shouldn't ask this in the comments. Either edit your question to properly reflect your question or open a new one - Tomerikoo

2 Answers

1
votes

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
1
votes

You cannot declare a wire inside the always block.

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

always @(posedge clk) begin
    f_zero <= tmp_wire & 'hFF == 0;
    f_carry <= tmp_wire & 'h100;
end