verilogiverilog

Trying to design a shift adder using Verilog, and I'm not able to fix this error


I was implementing a 4-bit shift adder using Verilog, and I was facing an issue with the following code:

//shift register to store the two inputs a and b to be added
module shift(y, d, clk);
  input [3:0] d;
  input clk;
  output [3:0] y;
  reg [3:0] y;
  initial begin
    assign y=d;
  end

  always @(posedge clk)
    assign y= {1'b0, d[3:1]};
endmodule

//serial in parallel out register to store the 4 bit sum
module sipo(y, s, clk);
  input  s, clk;
  output [3:0] y;
  reg [3:0] y;
  always @(posedge clk)
    begin
      y={s,y[3:1]};
    end
endmodule

//1 bit full adder
module fa(s, cout, a, b, cin);
  input a, b, cin;
  output s, cout;
  assign {cout, s} = a + b + cin;
endmodule

//d flipflop to store the cout of each stage
module dff(q, d, clk);
  input d, clk;
  output q;
  reg q;
  initial begin
    q = 1'b0;
  end
  always @(posedge clk)
    begin
      q = d;
    end
endmodule

//main module serial adder//
module serial(sum, cout, a, b, clk);
  input [3:0] a, b;
  input clk;
  wire [3:0] x, z;
  output [3:0] sum; 
  output cout;
  wire s = 0;
  wire cin = 0;
  fa k(s, cout, x[0], z[0], cin);     //1 bit full adder
  dff q(cin, cout, clk);              //d flipflop to store the cout value after each 1 bit full adder operation
  sipo m(sum, s, clk);                //serial sum(s) converted to parallel output(4 bit sum)///
  shift g(x, a, clk);                 //shifts the input a
  shift h(z, b, clk);                 //shifts the input b
endmodule

module SATestBench;
  reg [3:0] a, b;
  reg clock;
  wire  cout;
  wire  [3:0] sum;
  serial  sa(sum, cout, a, b, clock);
  initial begin
    #5  clock = 1'b0;
    repeat(6)
    # 5 clock = ~clock;
  end
  initial begin
    #0  a = 4'b1000;  b=4'b0110;
    $monitor($time, " A = %b, B = %b, CarryOut = %b, Sum = %b.", sa.x, sa.z, cout, sum);
  end
endmodule

The error I was receiving was "vvp.tgt sorry: procedural continuous assignments are not yet fully supported. The RHS of this assignment will only be evaluated once, at the time the assignment statement is executed." I searched a bit online, and I found from here that assign isn't allowed in always blocks.

Then I tried removing the assign block, and then the output for Sum/CarryOut was only "x"s. I'm not able to fix this, I've tried for many hours now. I've just started learning Verilog, so I apologise if this is a novice mistake.


Solution

  • In the following snapshot of your exampe assign used inside procedural blocks is the procedural continuous assignments which your message complains about.

      initial begin
        assign y=d;
      end
    
      always @(posedge clk)
        assign y= {1'b0, d[3:1]};
    

    This is a very special non-synthesizable statement seldom used if at all. You should avoid it.

    Get rid of this keyword if it is used inside such a statemetn.

      initial begin
        y=d;
      end
    
      always @(posedge clk)
        y <= {1'b0, d[3:1]};
    

    Now you have a multiple-driver problem. Variable y is driven from two different procedural blocks. You should change that and use a reset instead:

      always @(posedge clk) begin
         if (reset)
            y <= d;
         else
            y <= {1'b0, d[3:1]};
    

    So, for that you should provide a reset.