代码仅通过仿真测试模拟正确无误
代码部分:
module multiple
(
input clk,
input rst_n, // 复位信号,低电平有效
input sel_a, // 被乘数选择信号
input sel_b, // 乘数选择信号
input hold_sel, // 选择保持信号
input [7:0] num, // 输入数据
output [2:0] display_sel, // 数码管显示位选信号
output [7:0] display_num // 数码管显示数字编码
);
reg [14:0] product_reg; // 结果寄存器
reg [15:0] product; // 乘积结果
reg [6:0] multiplicand; // 被乘数寄存器
reg [6:0] multiplier; // 乘数寄存器
reg [3:0] count; // 乘积计数器(CP)
reg [6:0] a; // 被乘数
reg sign_a; // 被乘数符号位
reg [6:0] b; // 乘数
reg sign_b; // 乘数符号位
reg [1:0] dis_count; // 晶体管显示计数器
reg [2:0] delay_display_sel_reg; // 数码管显示选择寄存器(延时一个时钟周期)
reg [2:0] display_sel_reg; // 数码管显示选择寄存器
reg [7:0] display_num_reg; // 数码管显示数值寄存器
reg [3:0] selected_num; // 选中的要显示的数值
//===================数据输入部分====================//
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
a <= 7'b0;
sign_a <= 0;
sign_b <= 0;
b <= 7'b0;
end
else begin
if((!sel_a&&!sel_b || sel_a && sel_b)&&!hold_sel)begin
a <= 7'b0;
b <= 7'b0;
end
else if(sel_a) begin
a <= num[6:0];
sign_a <= num[7];
end
else if(sel_b) begin
b <= num[6:0];
sign_b <= num[7];
end
end
end
//===================乘法器部分====================//
//采用移位加法器实现乘法运算,将n位乘法转化为n次加法和n次移位操作
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
product_reg <= 15'b0;
multiplicand <= 7'b0;
multiplier <= 7'b0;
count <= 4'b0;
end else begin
if (count == 0) begin
product <= {sign_a^sign_b,product_reg};
product_reg <= 15'b0;
multiplicand <= a;
multiplier <= b;
count <= 4'd7;
end else begin
if (multiplier[0])
product_reg <= product_reg + {8'b0, multiplicand};
multiplicand <= multiplicand << 1;
multiplier <= multiplier >> 1;
count <= count - 1;
end
end
end
//===================数码管显示计数器部分====================//
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
dis_count<=3;
end
else begin
if(dis_count == 2'd3)dis_count <= 2'd0;
else dis_count <= dis_count + 2'd1;
end
end
//===================计数器选择显示数码管部分====================//
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
selected_num <= 0;
display_sel_reg <= 0;
end
else begin
case(dis_count)
2'd3:begin
selected_num <= product[3:0];
display_sel_reg <= 3'd3;
end
2'd2:begin
selected_num <= product[7:4];
display_sel_reg <= 3'd2;
end
2'd1:begin
selected_num <= product[11:8];
display_sel_reg <= 3'd1;
end
2'd0:begin
selected_num <= product[15:12];
display_sel_reg <= 3'd0;
end
default:begin
selected_num <= 4'd0;
display_sel_reg <= 3'd0;
end
endcase
end
end
//===================数码管显示数字译码部分====================//
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
display_num_reg <= 8'd0;
end
else begin
case(selected_num)
4'd0: display_num_reg <= 8'h3f;
4'd1: display_num_reg <= 8'h06;
4'd2: display_num_reg <= 8'h5b;
4'd3: display_num_reg <= 8'h4f;
4'd4: display_num_reg <= 8'h66;
4'd5: display_num_reg <= 8'h6d;
4'd6: display_num_reg <= 8'h7d;
4'd7: display_num_reg <= 8'h07;
4'd8: display_num_reg <= 8'h7f;
4'd9: display_num_reg <= 8'h6f;
4'd10: display_num_reg <= 8'h77;
4'd11: display_num_reg <= 8'h7c;
4'd12: display_num_reg <= 8'h39;
4'd13: display_num_reg <= 8'h5e;
4'd14: display_num_reg <= 8'h79;
4'd15: display_num_reg <= 8'h71;
default:display_num_reg <= 8'h00;
endcase
end
end
//===================数码管显示位选信号延时====================//
//这里由于数码管显示数字译码部分对输入的selected_num信号进行译码有一个时延,所以需要将数码管显示位选信号延时一个时钟周期
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
delay_display_sel_reg <= 3'd0;
end
else begin
delay_display_sel_reg <= display_sel_reg;
end
end
assign display_num = display_num_reg;
assign display_sel = delay_display_sel_reg;
endmodule
仿真图象:
可以看到位选信号和数字是一一对应的,乘积运算也无误
引脚分配
clk | PIN_A14 |
rst_n | PIN_AF5 |
sel_a | PIN_AE3 |
sel_b | PIN_AD4 |
hold_sel | PIN_U8 |
num[7] | PIN_AH12 |
num[6] | PIN_AF14 |
num[5] | PIN_AA8 |
num[4] | PIN_AB8 |
num[3] | PIN_AE4 |
num[2] | PIN_AC5 |
num[1] | PIN_AF12 |
num[0] | PIN_AG12 |
display_sel[2] | PIN_G9 |
display_sel[1] | PIN_D22 |
display_sel[0] | PIN_C22 |
display_num[7] | PIN_M21 |
display_num[6] | PIN_G12 |
display_num[5] | PIN_G14 |
display_num[4] | PIN_G15 |
display_num[3] | PIN_G18 |
display_num[2] | PIN_F18 |
display_num[1] | PIN_G17 |
display_num[0] | PIN_G16 |
使用方法:
拨动num对应的开关来输入数据,输入数据时将hold_sel开关拨至高电平,作用是维持输入的数据,使其保持不变;sel_a拨至高电平则输入数据至a寄存器,sel_b同理。按下S1 按钮则进行复位。注意调整开发板右下角的时钟频率,至1khz显示效果较好