【SWJTU】计算机组成实验-课程实验三-原码一位乘法运算器设计

代码仅通过仿真测试模拟正确无误

代码部分:

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

仿真图象:

可以看到位选信号和数字是一一对应的,乘积运算也无误

引脚分配

clkPIN_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显示效果较好

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值