Verilog Code,使用add和shift的顺序乘法器

时间:2014-06-07 06:48:50

标签: verilog fsm multiplying

这是我的顺序加/移倍增器的verilog代码。我收到“XXXXXXX”作为输出,如果我将复位设置为高,我会收到所有零作为输出。有人可以帮我辨别我做错了什么吗?

感谢您提供任何提示/提示。

module MULTIPLY_revision (
  input              clk, reset, start,
  input       [7:0]  A_in, B_in,
  output reg         done_tick,
  output wire [15:0] product 
);

localparam [1:0]
    idle  = 2'b00,
    op    = 2'b01,
    shift = 2'b10;

// signal declaration
reg       carry, next_carry;
reg [1:0] state, next_state;
reg [7:0] reg_PL, PL, reg_PH, PH, reg_a_multiplicand, a_multiplicand;   
reg [4:0] counter, next_counter;

assign product = {reg_PH, reg_PL};

always @(posedge clk, posedge reset)
  if (reset) begin
    state              <= idle;
    counter            <= 0;
    carry              <= 0;
    reg_PL             <= 0;
    reg_PH             <= 0;
    reg_a_multiplicand <= 0;
  end
  else begin
    state              <= next_state;
    carry              <= next_carry;
    counter            <= next_counter;
    reg_PL             <= PL;
    reg_PH             <= PH;
    reg_a_multiplicand <= a_multiplicand; 
  end

// next state logic 
always @ * begin
  done_tick      = 1'b0;
  PL             = reg_PL;
  PH             = reg_PH;
  a_multiplicand = reg_a_multiplicand; 
  next_carry     = carry;
  next_counter   = counter;
  next_state     = state;

  case(state)
    idle: begin
      if(start) begin
        next_counter   = 7; // load 7 for 8 bits down counter
        PL             = B_in; // load multiplier into lower half
        PH             = 8'b0; // clear upper half. 
        a_multiplicand = A_in; // load A multiplicand into register. 
        next_state     = op;
      end
    end

    op: begin
      if(reg_PL[0] == 1) begin
        {next_carry,PH} = reg_PH + reg_a_multiplicand;      // add A multiplicand to upper half with carry bit. 
      end
      next_counter = counter - 1;
      next_state   = shift;             
    end

    shift: begin
      {next_carry,PH,PL} = {carry,reg_PH,reg_PL} >> 1;  // putting everything back together and shifting everything to the right once. 
      if(next_counter == 0) begin
        next_state = idle;
      end
      else begin
        next_state = op;
      end
    end

    default: begin
      next_state = idle;
    end
  endcase
end


endmodule


   `timescale 1ns / 1ps

这是我的测试平台:任何关于如何编写更好的技巧的提示都会很棒。

module mytest;

// Inputs
reg clk;
reg reset;
reg start;
reg [7:0] A_in;
reg [7:0] B_in;

// Outputs
wire done_tick;
wire [15:0] product;

// Instantiate the Unit Under Test (UUT)
MULTIPLY_revision uut (
    .clk(clk), 
    .reset(reset), 
    .start(start), 
    .A_in(A_in), 
    .B_in(B_in), 
    .done_tick(done_tick), 
    .product(product)
);


initial begin
    // Initialize Inputs
    clk = 0;
    reset = 0;
    start = 0;
    A_in = 0;
    B_in = 0;

    // Wait 100 ns for global reset to finish
    #100;

            clk = 1;
    reset = 0;
    start = 1;
    A_in = 4;
    B_in = 4;

    #100

    clk = 1;
    reset = 0;
    start = 1;
    A_in = 5;
    B_in = 6;

    end

always
#20 clk = !clk;


endmodule

2 个答案:

答案 0 :(得分:0)

正如Ciano指出的那样,你并没有正确启动时钟。你也永远不会在TB中断言重置。

initial clk = 0;
always clk = #20 ~clk;

initial
  begin
    reset = 1;
    // set all inputs to quiescent
    #100;
    reset = 0;
    // continue stimulus
  end

答案 1 :(得分:0)

以下内容可帮助您测试模块。但似乎你的模块不起作用。

initial begin
    // Initialize Inputs
    clk = 0;
    reset = 0;
    start = 0;
    A_in = 0;
    B_in = 0;

     @(posedge clk);
     reset = 1;
     repeat(2)@(posedge clk); 
     reset = 0;
     @(posedge clk); 
     start = 1 ;
     A_in = 5;
    B_in = 6;
     wait(done_tick == 1);
     $display("A_In = %d B_In = %d Product =  %d",A_in,B_in,product);





    end

always
#20 clk = !clk;