简体   繁体   中英

My Verilog behavioral code getting simulated properly but not working as expected on FPGA

I wrote a behavioral program for booth multiplier(radix 2) using state machine concept. I am getting the the results properly during the program simulation using modelsim, but when I port it to fpga (spartan 3) the results are not as expected.

Where have I gone wrong?

module booth_using_statemachine(Mul_A,Mul_B,Mul_Result,clk,reset);

input Mul_A,Mul_B,clk,reset;
output Mul_Result;
wire [7:0] Mul_A,Mul_B;
reg [7:0] Mul_Result;


reg [15:0] R_B;
reg [7:0] R_A;
reg prev;
reg [1:0] state;
reg [3:0] count;

parameter start=1 ,add=2 ,shift=3;
always @(state)
begin

case(state)
 
  start:
   begin
      R_A   <= Mul_A;
      R_B   <= {8'b00000000,Mul_B};
      prev  <= 1'b0;
      count <= 3'b000;
      Mul_Result <= R_B[7:0];
     end
     
   add:
   begin
    
     case({R_B[0],prev})
            
         2'b00:
           begin
             prev <= 1'b0;
            end
         
         2'b01:
           begin
             R_B[15:8] <= R_B[15:8] + R_A;
         prev      <= 1'b0;
            end
         
         2'b10:
         begin
              R_B[15:8] <= R_B[15:8] - R_A;
              prev      <= 1'b1;
             end
         
         2'b11:
            begin
              prev <=1'b1;
             end
        
        endcase
        
    end
  
  shift:
   begin
     R_B  <= {R_B[15],R_B[15:1]};
     count <= count + 1;
    end
    
endcase
    
     
end  
     

  always @(posedge clk or posedge reset)
  begin
 
   if(reset==1)
      state <= start;
    
    else
      begin
       
        case(state)
           
            start:
              state <= add;
            
            add:
              state <= shift;
              
            
            shift:
              begin
                
                 if(count>7)
                  state <= start;
            
            else
              state <=add;
           
                end
                            
    
        
     endcase
  end
  end   
 endmodule

You have an incomplete sensitivity list in your combinational always block. Change:

always @(state)

to:

always @*

This may be synthesizing latches.

Use blocking assignments in your combinational always block. Change <= to = .

Good synthesis and linting tools should warn you about these constructs.

Follow the following checklist if something does work in the simulation but not in reality:

  • Did you have initialized every register? (yes)
  • Do you use 2 registers for one working variable that you transfer after each clock (no) (use for state 2 signals/wires, for example state and state_next and transfer after each clock state_next to state)

A Example for the second point is here , you need the next stage logic, the current state logic and the output logic.

For more informations about how to proper code a FSM for an FPGA see here (go to HDL Coding Techniques -> Basic HDL Coding Techniques)

You've got various problems here.

  1. Your sensitivity list for the first always block is incomplete. You're only looking at state , but there's numerous other signals which need to be in there. If your tools support it, use always @* , which automatically generates the sensitivity list. Change this and your code will start to simulate like it's running on the FPGA.

    This is hiding the other problems with the code because it's causing signals to update at the wrong time. You've managed to get your code to work in the simulator, but it's based on a lie. The lie is that R_A , R_B , prev , count & Mul_Result are only dependent on changes in state, but there's more signals which are inputs to that logic.

  2. You've fallen into the trap that the Verilog keyword reg creates registers. It doesn't. I know it's silly, but that's the way it is. What reg means is that it's a variable that can be assigned to from a procedural block. wire s can't be assigned to inside a procedural block.

    A register is created when you assign something within a clocked procedural block (see footnote), like your state variable. R_A , R_B , prev and count all appear to be holding values across cycles, so need to be registers. I'd change the code like this:

First I'd create a set of next_* variables. These will contain the value we want in each register next clock.

reg [15:0] next_R_B;
reg [7:0]  next_R_A;
reg        next_prev;
reg [3:0]  next_count;

Then I'd change the clocked process to use these:

always @(posedge clk or posedge reset) begin

 if(reset==1) begin
   state <= start;
   R_A   <= '0;
   R_B   <= '0;
   prev  <= '0;
   count <= '0;
 
 end else begin
   R_A   <= next_R_A;
   R_B   <= next_R_B;
   prev  <= next_prev;
   count <= next_count;

   case (state)
   .....

Then finally change the first process to assign to the next_* variables:

always @* begin
  next_R_A   <= R_A;
  next_R_B   <= R_B;
  next_prev  <= prev;
  next_count <= count;

  case(state)
    
    start: begin
      next_R_A   <= Mul_A;
      next_R_B   <= {8'b00000000,Mul_B};
      next_prev  <= 1'b0;
      next_count <= 3'b000;
      Mul_Result <= R_B[7:0];
    end

    add: begin

      case({R_B[0],prev})
        2'b00: begin
          next_prev <= 1'b0;
        end
        
    .....

Note:

  • All registers now have a reset
  • The next_ value for any register defaults to it's previous value.
  • next_ values are never read, except for the clocked process
  • non- next_ values are never written, except in the clocked process.

I also suspect you want Mul_Result to be a wire and have it assign Mul_Result = R_B[7:0]; rather than it being another register that's only updated in the start state, but I'm not sure what you're going for there.


  • A register is normally a reg , but a reg doesn't have to be a register.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM