我正在尝试根据设计编写乘数。它由两个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。
答案 0 :(得分: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
传播到总和。
对更新代码的评论:
=
代替<=
。 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;
答案 1 :(得分:0)
您正在同一顺序always
块中混合阻止和非阻止分配,这可能会导致意外结果:
d_in <= p_high[15];
p_low[14] = d_in;