编写乘法器求解算法表达式
描述
编写一个4bit乘法器模块,并例化该乘法器求解c=12*a+5*b,其中输入信号a,b为4bit无符号数,c为输出。注意请不要直接使用*符号实现乘法功能。
模块的信号接口图如下:
要求使用Verilog HDL语言实现以上功能,并编写testbench验证模块的功能。
输入描述:
clk:系统时钟信号
rst_n:复位信号,低电平有效
a:输入信号,位宽为4bit
b:输入信号,位宽为4bit
输出描述:
c:输出信号
解题思路:
移位运算与乘法的关系如下:
左移n位表示乘;
右移n位表示除;
当直接在一个always语句块中写入代码,如下所示:
cpp
`timescale 1ns/1ns
module calculation(
input clk,
input rst_n,
input [3:0] a,
input [3:0] b,
output [8:0] c
);
wire [8:0] a_9, b_9;
reg [8:0] c_r;
assign a_9 = {5'b0_0000, a[3:0]};
assign b_9 = {5'b0_0000, b[3:0]};
always @(posedge clk or negedge rst_n) begin
if (!rst_n) c_r <= 9'b0_0000_0000;
else c_r <= (a_9<<3)+(a_9<<2)+(b_9<<2)+b_9;
end
assign c = c_r;
endmodule
可发现其波形如下:
如红色方框所示,最终输出C的值是在第二个时钟上升沿的到来时才正常输出,因此在信号a,b输入时,应该打一拍;
正确的代码如下:
cpp
`timescale 1ns/1ns
module calculation(
input clk,
input rst_n,
input [3:0] a,
input [3:0] b,
output [8:0] c
);
reg [8:0] a_9, b_9;
reg [8:0] c_r;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
a_9 <= 9'b0_0000_0000;
b_9 <= 9'b0_0000_0000;
end
else begin
a_9 <= {5'b0_0000, a[3:0]};
b_9 <= {5'b0_0000, b[3:0]};
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) c_r <= 9'b0_0000_0000;
else c_r <= (a_9<<3)+(a_9<<2)+(b_9<<2)+b_9;
end
assign c = c_r;
endmodule