0

我正在尝试根据设计编写乘数。它由两个 16 位输入组成,单个加法器用于计算部分乘积。一个输入的 LSB 与另一个输入的 16 位进行“与”运算,并且与门的输出重复地与前一个输出相加。它的 Verilog 代码如下,但我似乎无法让输出正常工作。

module datapath(output reg [31:15]p_high,
                output reg [14:0]p_low,
                input [15:0]x, y,
                input clk); // reset, start, x_ce, y_ce, y_load_en, p_reset, 
               //output done);

reg [15:0]q0;
reg [15:0]q1;
reg [15:0]and_output;
reg [16:0]sum, prev_sum; 
reg d_in;
reg [3:0] count_er;

initial
 begin
      count_er <= 0;
      sum <= 17'b0;
      prev_sum <= 17'b0;
 end

always@(posedge clk)
begin
        q0 <= y;
        q1 <= x;
        and_output <= q0[count_er] & q1;
        sum <= and_output + prev_sum;    
        prev_sum <= sum;
        p_high <= sum;
        d_in <= p_high[15];
        p_low[14] <= d_in;
        p_low <= p_low >> 1;
        count_er <= count_er + 1;
 end
 endmodule

在此处输入图像描述 我创建了一个测试台来测试电路,我看到的第一个问题是,AND 操作没有按我的意愿工作。x 操作数的 16 位与 y 操作数的 LSB 进行“与”运算。y 操作数在每个时钟周期后移动一位,并通过连续添加部分乘积来计算最终乘积。

但是,我从 sum 和 prev_sum 行开始遇到问题,它们的输出显示为 xxxxxxxxxxxx。

4

2 回答 2

1

您似乎没有正确重置您需要的所有信号,或者您似乎对非阻塞分配的工作方式感到困惑。

初始开始后:

  • sum是 0
  • prev_sum是 0
  • and_output是 X

在第一个上升沿之后:

  • sum是 X,因为and_output是 X,并且 X+0 返回 X。此时 sum 永远保持 X,因为 X + 某事始终是 X。

您正在为设计中的几乎每个信号创建一个寄存器,这意味着您的任何信号都不会立即更新。您需要区分要注册的信号和只是组合术语的信号。让寄存器用 上的非阻塞语句更新posedge clock,并通过将组合项放在一个always @*块中来让它们立即更新。

我不知道您要使用的算法,所以我不能说哪条线应该是哪条线,但我真的怀疑您是否打算让它花费一个时钟周期x/y传播到q0/q1,另一个周期传播q到传播到and_output,还有另一个时钟周期从传播and_output到总和。


对更新代码的评论:

  • 组合块应该使用阻塞赋值,而不是非阻塞赋值。在 always @* 块内使用=而不是。<=
  • sum <= and_output + sum;看起来不对,应该是sum = and_output + p_high[31:16]根据你的图片。
  • 您在这里分配 p_low[14] 两次。使第二条语句仅显式设置位 [13:0]:

    p_low[14]   <= d_in;
    p_low[13:0] <= p_low >> 1;
    
于 2013-03-23T01:43:18.927 回答
0

您在同一个顺序always块中混合了阻塞和非阻塞分配,这可能会导致意外结果:

d_in <= p_high[15];
p_low[14] = d_in;
于 2013-03-23T00:01:22.620 回答