Bodizzy
Bodizzy

Reputation: 11

Instantiating a value in or out of an always block

I have written a piece of code that will return a quotient and a reminder, based on numbers that i provide and some other data that i used to shift the numbers in place.
The problem I have now is that i cannot keep a good track of my quotient if I test more values one after another.
I need a way to initialize my cat register, so that I no longer get residual values from previous computations.

Here is the code I was talking about:

module divide(
  input      [7:0] a, b,
  input      [3:0] counter, msb,
  output reg [7:0] q,
  output reg [7:0] r
);
always @(*) begin
  for(i = 0; i < counter + 1  ; i = i+1) begin
    sum = s_a + s_b;     //previously calculated values
      if(sum[8-msb] == 1) begin
        assign s_a       = s_a; 
        assign s_b       = s_b >>> 1;
        cat[counter - i] = 1'b0;                
      end
      else begin
        assign s_a       = sum;
        assign s_b       = s_b >>> 1;
        cat[counter - i] = 1'b1;
      end
      assign r = s_a;
      assign q = cat;
    end
  end
endmodule 

Note: I have declared all the registers that are in this code, but for some purpose I cannot declare them here.

Upvotes: 0

Views: 1493

Answers (1)

Morgan
Morgan

Reputation: 20514

You do not use assign inside always or initial blocks.

The assignments to cat are combinatorial therefore it is not a flip-flop, ie has no reset. The fact that it is a reg type has nothing to do with the hardware but a simulator optimisation.

I would have written it as (no functional alterations made):

module divide#(
  parameter DATA_W = 8
)(
  input      [7:0] a, b,
  input      [3:0] counter, msb,
  output reg [7:0] q,
  output reg [7:0] r
);
//Definitions
reg [DATA_W-1:0] sum;
reg [DATA_W-1:0] s_a;
reg [DATA_W-1:0] s_b;
integer i;

always @* begin
  for(i = 0; i < (counter + 1); i = i+1) begin
    sum = s_a + s_b;     //previously calculated values
      if(sum[8-msb] == 1'b1) begin
       s_a              = s_a; 
       s_b              = s_b >>> 1;
       cat[counter - i] = 1'b0;                
      end
      else begin
        s_a              = sum;
        s_b              = s_b >>> 1;
        cat[counter - i] = 1'b1;
      end
      r = s_a;
      q = cat;
    end
  end
endmodule

You have the following line:

sum = s_a + s_b;     //previously calculated values

You have not included any flip-flops here, unless you have implied latches which are really to be avoided, there is no memory or state involved. i.e. there are no previously calculated values.

Instead of a combinatorial block you likely want to add a flip-flop and take multiple clock cycles to calculate the result.

instead of an always @* try:

always @(posedge clk or negedge rst_n) begin
  if (~rst_n) begin
     s_a <= 'b0; //Reset Value
  end
  else begin 
    s_a <= next value; //Normal logic
  end
end

Upvotes: 3

Related Questions