注:相应的源文件在文末的github链接中
实验六 8位乘法器设计与实现
一.实验要求
1、设计无符号乘法器,将两个8位无符号数相乘,得到一个16位无符号数。
2、设计有符号乘法器,将两个8位有符号数相乘,得到一个16位有符号数。
3、设计按键输入转换电路,设计七段显示器显示和控制电路: 通过8个按键输入两个4位的二进制乘数A和B,两个乘数和乘积的结果,分别送给多个七段显示器进行显示。
注:基础的80分验收代码我并未保存,但进入实验室后老师会给出无需担心
二.设计无符号乘法器:将两个16位无符号数相乘,得到一个32位无符号数()
要求
在Vivado中设计输入控制电路,将按键sw0~sw3对应于一个四位的二进制数A[3:0],设计一个二进制数到8421BCD码的转换电路,将得到的8421BCD码的数值显示在两个数码管上。类似的,将按键sw4~sw7对应于一个四位的二进制数B[3:0],设计一个二进制数到8421BCD码的转换电路,将得到的8421BCD码的数值显示在另外两个数码管上。
源文件
module main(
input [3:0]A,
input [3:0]B,
input clk,
//output [7:0] res,
output [7:0]an,//显示哪一个亮
output [7:0]seg,//亮的那一个是什么(乘数)
output [7:0]seg1//亮的那一个是什么(乘积)
);
wire clock_25m;
wire [7:0] res;
multu_4bit m4(clk,A, B, res); //乘法电路
//分频模块
clock_division cd(clk, clock_25m);
//计数器模块
wire [3:0]state;
counter C(clock_25m,state);
//输出模块(位选+段选)
Show out(an,seg,seg1,A,B,res,state); //输出电路
Endmodule
module clock_division(clk_in,divclk);
input clk_in;
output divclk;
parameter DIVCLK_CNTMAX = 32'd51200; //时钟分频计数的最大值
reg [31:0] cnt = 0;
reg divclk_reg = 0;
always@(posedge clk_in) begin
if(cnt == DIVCLK_CNTMAX) begin
cnt <= 0;
divclk_reg <= ~divclk_reg;
end
else
cnt <= cnt + 1;
end
assign divclk = divclk_reg;
endmodule
module counter(
input clock_25m,
output state
);
//计数器模块
reg [2:0] state = 0; //一共8个管,需要3位
always@(posedge clock_25m) begin
if(state == 3'b111)
state <= 3'b000;
else
state <= state + 1'b1;
end
endmodule
module Show(
output reg [7:0] an,
output reg [7:0] seg,
output reg [7:0] seg1,
input [3:0]A, //A
input [3:0]B, //B
input [7:0]res, //res
input [2:0]state
);
reg [3:0] bcd;
//an 的哪一位是1说明当前,这一位对应的序号的数码管要亮
//分别代表
always @(*) begin
case(state)
//显示A(十)
3'b000: begin
an = 8'b00000001;
bcd = A / 10;
end
//显示A(个)
3'b001: begin
an = 8'b00000010;
bcd = A % 10;
end
//显示B(十)
3'b010: begin
an = 8'b00000100;
bcd = B / 10;
end
//显示B(个)
3'b011: begin
an = 8'b00001000;
bcd = B % 10;
end
//显示res(千)
3'b100: begin
an = 8'b00010000;
bcd = res / 1000;
end
//显示res(百)
3'b101: begin
an = 8'b00100000;
bcd = (res / 100)%10;
end
//显示res(十)
3'b110: begin
an = 8'b01000000;
bcd = (res / 10) % 10;
end
//显示res(个)
3'b111: begin
an = 8'b10000000;
bcd = res % 10;
end
endcase
end
//8421BCD码bcd与一位数码管的8段A、B、C、D、E、F、G、DP之间的对应关系
always @(*) begin
case(bcd)
4'h0:
begin
seg = 8'hfc;
seg1 = 8'hfc;
end
4'h1:
begin
seg = 8'h60;
seg1 = 8'h60;
end
4'h2:
begin
seg = 8'hda;
seg1 = 8'hda;
end
4'h3:
begin
seg = 8'hf2;
seg1 = 8'hf2;
end
4'h4:
begin
seg = 8'h66;
seg1 = 8'h66;
end
4'h5:
begin
seg = 8'hb6;
seg1 = 8'hb6;
end
4'h6:
begin
seg = 8'hbe;
seg1 = 8'hbe;
end
4'h7:
begin
seg = 8'he0;
seg1 = 8'he0;
end
4'h8:
begin
seg = 8'hfe;
seg1 = 8'hfe;
end
4'h9:
begin
seg = 8'hf6;
seg1 = 8'hf6;
end
default:
begin
seg = 8'h00; //八段全熄灭
seg1 = 8'h00; //八段全熄灭
end
endcase
end
endmodule
module multu_4bit(
input clk, //乘法器时钟信号
input [3:0] a, //输入a(被乘数)
input [3:0] b, //输入b(乘数)
output reg [7:0] sum = 0 //乘积输出sum
);
integer n = 3;
always@(posedge clk)
begin
for(n = 3; n >= 0; n = n-1)
begin
if(b[n] == 1'b0)
begin
sum = sum + 0;
sum = sum << 1;
end
else if(b[n] == 1'b1)
begin
sum = sum + a;
sum = sum << 1;
end
end
end
endmodule
引脚约束
set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33} [get_ports {seg[0]}]
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports {seg[1]}]
set_property -dict {PACKAGE_PIN D3 IOSTANDARD LVCMOS33} [get_ports {seg[2]}]
set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33} [get_ports {seg[3]}]
set_property -dict {PACKAGE_PIN F3 IOSTANDARD LVCMOS33} [get_ports {seg[4]}]
set_property -dict {PACKAGE_PIN E2 IOSTANDARD LVCMOS33} [get_ports {seg[5]}]
set_property -dict {PACKAGE_PIN D2 IOSTANDARD LVCMOS33} [get_ports {seg[6]}]
set_property -dict {PACKAGE_PIN H2 IOSTANDARD LVCMOS33} [get_ports {seg[7]}]