FPGA初步-Verilog的乘法器
2015-09-24 08:37
344 查看
下面的代码是在论坛上参考了其他网友的程序,加上自己的理解
module
mux16(
clk,rst_n,
start,ain,bin,yout,done
);
input
clk; //芯片的时钟信号。
input
rst_n; //低电平复位、清零信号。定义为0表示芯片复位;定义为1表示复位信号无效。
input
start; //芯片使能信号。定义为0表示信号无效;定义为1表示芯片读入输入管脚得乘数和被乘数,并将乘积复位清零。
input[15:0]
ain; //输入a(被乘数),其数据位宽为16bit.
input[15:0]
bin; //输入b(乘数),其数据位宽为16bit.
output[31:0]
yout; //乘积输出,其数据位宽为32bit.
output
done; //芯片输出标志信号。定义为1表示乘法运算完成.
reg[15:0]
areg; //乘数a寄存器
reg[15:0]
breg; //乘数b寄存器
reg[31:0]
yout_r; //乘积寄存器
reg
done_r;
reg[4:0]
i; //移位次数寄存器
//------------------------------------------------
//数据位控制
always
@(posedge clk or negedge rst_n)
if(!rst_n)
i <= 5'd0;
else
if(start && i < 5'd17) i <= i+1'b1;
else
if(!start) i <= 5'd0;
//------------------------------------------------
//乘法运算完成标志信号产生
always
@(posedge clk or negedge rst_n)
if(!rst_n)
done_r <= 1'b0;
else
if(i == 5'd16) done_r <= 1'b1; //乘法运算完成标志
else
if(i == 5'd17) done_r <= 1'b0; //标志位撤销
assign
done = done_r;
//------------------------------------------------
//专用寄存器进行移位累加运算
always
@(posedge clk or negedge rst_n) begin
if(!rst_n)
begin
areg
<= 16'h0000;
breg
<= 16'h0000;
yout_r
<= 32'h00000000;
end
else
if(start) begin //启动运算
if(i
== 5'd0) begin //锁存乘数、被乘数
areg
<= ain;
breg
<= bin;
end
else
if(i > 5'd0 && i < 5'd16) begin
if(areg[i-1])
yout_r = {1'b0,yout[30:15]+breg,yout_r[14:1]}; //累加并移位..........1
else
yout_r <= yout_r>>1; //移位不累加
end
else
if(i == 5'd16 && areg[15]) yout_r[30:15] <= yout_r[30:15]+breg; //累加不移位...................2
end
end
assign
yout = yout_r;
endmodule
笔者的理解此程序的难点是:
1和2处
1处只拼接yout_r的1~14,也就是第二位到第十五位,这是因为例化程序后,第一次取出的yout_r为0,每加一次breg,拼接一次,就在最后位去掉一个零,并在最高位补零。
2处是笔者经过分析做了修改的版本,也请大家一起思考,笔者认为最后一次加法,是areg的最高位乘以breg,真实乘法计算时是左移15位的,原作者是
else
if(i == 5'd16 && areg[15]) yout_r[31:16] <= yout_r[31:16]+breg; //累加不移位
故在此处修改。
以上是笔者对初学Verilog的一种乘法器编译的学习
module
mux16(
clk,rst_n,
start,ain,bin,yout,done
);
input
clk; //芯片的时钟信号。
input
rst_n; //低电平复位、清零信号。定义为0表示芯片复位;定义为1表示复位信号无效。
input
start; //芯片使能信号。定义为0表示信号无效;定义为1表示芯片读入输入管脚得乘数和被乘数,并将乘积复位清零。
input[15:0]
ain; //输入a(被乘数),其数据位宽为16bit.
input[15:0]
bin; //输入b(乘数),其数据位宽为16bit.
output[31:0]
yout; //乘积输出,其数据位宽为32bit.
output
done; //芯片输出标志信号。定义为1表示乘法运算完成.
reg[15:0]
areg; //乘数a寄存器
reg[15:0]
breg; //乘数b寄存器
reg[31:0]
yout_r; //乘积寄存器
reg
done_r;
reg[4:0]
i; //移位次数寄存器
//------------------------------------------------
//数据位控制
always
@(posedge clk or negedge rst_n)
if(!rst_n)
i <= 5'd0;
else
if(start && i < 5'd17) i <= i+1'b1;
else
if(!start) i <= 5'd0;
//------------------------------------------------
//乘法运算完成标志信号产生
always
@(posedge clk or negedge rst_n)
if(!rst_n)
done_r <= 1'b0;
else
if(i == 5'd16) done_r <= 1'b1; //乘法运算完成标志
else
if(i == 5'd17) done_r <= 1'b0; //标志位撤销
assign
done = done_r;
//------------------------------------------------
//专用寄存器进行移位累加运算
always
@(posedge clk or negedge rst_n) begin
if(!rst_n)
begin
areg
<= 16'h0000;
breg
<= 16'h0000;
yout_r
<= 32'h00000000;
end
else
if(start) begin //启动运算
if(i
== 5'd0) begin //锁存乘数、被乘数
areg
<= ain;
breg
<= bin;
end
else
if(i > 5'd0 && i < 5'd16) begin
if(areg[i-1])
yout_r = {1'b0,yout[30:15]+breg,yout_r[14:1]}; //累加并移位..........1
else
yout_r <= yout_r>>1; //移位不累加
end
else
if(i == 5'd16 && areg[15]) yout_r[30:15] <= yout_r[30:15]+breg; //累加不移位...................2
end
end
assign
yout = yout_r;
endmodule
笔者的理解此程序的难点是:
1和2处
1处只拼接yout_r的1~14,也就是第二位到第十五位,这是因为例化程序后,第一次取出的yout_r为0,每加一次breg,拼接一次,就在最后位去掉一个零,并在最高位补零。
2处是笔者经过分析做了修改的版本,也请大家一起思考,笔者认为最后一次加法,是areg的最高位乘以breg,真实乘法计算时是左移15位的,原作者是
else
if(i == 5'd16 && areg[15]) yout_r[31:16] <= yout_r[31:16]+breg; //累加不移位
故在此处修改。
以上是笔者对初学Verilog的一种乘法器编译的学习
相关文章推荐
- 不知道数据库中表的列类型的前提下,使用JDBC正确的取出数据(转)
- rsync配合ssh在不稳定网络下传输大文件
- Unity 资源打包Assetbundle
- shell 监控局域网的主机是否up(转)
- MapView的应用
- 面试问题背后的“猫腻”
- 【SSH】——Struts2中的动态方法调用(二)
- Cookie和Session详细介绍
- Android LayoutInflater的inflate方法中attachToRoot的作用
- nyoj 20 吝啬的国度
- 专业实训题目需求分析
- javaEE__JSP指令
- 感觉各种知道,问答,百科的真实性和可信性都被网络营销给搞坏了
- mysql 查询语句优化实例
- 括号配对
- javaEE__jsp
- 括号配对
- OpenGL研究2.0 计算圆
- Java表达式类型自动提升
- Leecode_Peeking Iterator