数字IC笔试题|Verilog求两个8bit数的最小公倍数、最大公约数(实现两个8bit数除法运算)

在这里插入图片描述
题目如上
解题思路:先利用辗转相除法求这个两个数的最大公约数,然后最小公倍数=两数乘积/最大公约数
所以问题的核心就转换为:
1.Verilog实现辗转相除法
2.Verilog实现除法

程序如下
求最小公倍数的程序如下:

module LCM_cal(a,b,en,clk,rst_n,lcm,lcm_val);
input [7:0] a,b; 
input en;
input clk,rst_n;
output [15:0]lcm;
output reg lcm_val;

wire [7:0] gcd;
wire gcd_valid;

GCD_cal my_gcd_cal(.en(en),.rst_n(rst_n),.clk(clk),.daA(a),.daB(b),.gcd(gcd),.gcd_valid(gcd_valid));

reg [15:0] gcd_reg;

always@(posedge clk or negedge rst_n)
begin 
if(rst_n==1'b0)
    gcd_reg<=16'b0;
else if(gcd_valid==1'b1)
    gcd_reg<={{8{1'b0}},gcd};
end 

always@(posedge clk or negedge rst_n)
begin 
if(rst_n==1'b0)
    lcm_val<=1'b0;
else if(gcd_valid==1'b1)
    lcm_val<=1'b1;
else 
    lcm_val<=1'b0;
end 

reg  [15:0] product;
wire [15:0] non;
always@(posedge clk or negedge rst_n)
begin 
if(rst_n==1'b0)
   product<=16'b0;
else if(en==1'b1)
   product<=a*b;
else 
   product<=product;
end 

div_cal #(.width(16)) my_div_cal 
(.a(product), 
 .b(gcd_reg),
 .shang(lcm),
 .yushu(non)
);
endmodule 

仿真结果如下:
在这里插入图片描述
verilog 实现除法的程序如下:

module div_cal
#(
   parameter width = 8
 )
(
input[width-1:0] a, 
input[width-1:0] b,
 
output reg [width-1:0] shang,
output reg [width-1:0] yushu
);

reg[width-1:0] tempa;
reg[width-1:0] tempb;
reg[2*width-1:0] temp_a;
reg[2*width-1:0] temp_b;
 
integer i;
always @(*)
begin
    temp_a = {{width{1'b0}},a};
    temp_b = {b,{width{1'b0}}}; 
    for(i = 0;i < width;i = i + 1)
        begin
            temp_a = temp_a<<1'b1;
            if(temp_a[2*width-1:width] >= b)
                temp_a = temp_a - temp_b + 1'b1;
            else
				temp_a = temp_a;
        end
 
    shang <= temp_a[width-1:0];
    yushu <= temp_a[2*width-1:width];
end
 
endmodule 

verilog实现辗转相除法的程序如下:

module GCD_cal(en,rst_n,clk,daA,daB,gcd,gcd_valid);
input en;          //数据有效,开始计算最小公约数
input clk;
input rst_n;
input [7:0]daA;
input [7:0]daB;
output reg [7:0]gcd;
output reg gcd_valid;

parameter idle=2'b00,div=2'b01,cal=2'b10,out=2'b11;

reg [1:0] state;

reg [7:0] tempa,tempb;
reg en_reg;

always@(posedge clk or negedge rst_n)
begin 
if(rst_n==1'b0)
    begin 
	   tempa<=8'b0000_0000;
		tempb<=8'b0000_0000;
	 end 
else if(en==1'b1)
    begin
	   if(daA>daB)
		    begin 
	       tempa<=daA;
		    tempb<=daB;
		    end 
		else
		    begin 
		    tempa<=daB;
		    tempb<=daA;
			 end 
	 end 
else 
    begin 
	   tempa<=tempa;
		tempb<=tempb;
	 end 
end 
reg en_test;
always@(posedge clk or negedge rst_n)
begin 
if(rst_n==1'b0)
   begin 
	en_reg<=1'b0;
   en_test<=1'b0;
	end 
else 
   begin 
	en_reg<=en;
   en_test<=en_reg;
	end 
end 
reg[7:0] a,b;
wire [7:0] yushu,shang;
always@(posedge clk or negedge rst_n)
begin 
if(rst_n==1'b0)
   begin 
	gcd<=8'b0000_0000;
	a<=8'b0000_0000;
	b<=8'b0000_0000;
	state<=idle;
	gcd_valid<=1'b0;
	end 
else 
   begin 
   case (state)
		 idle:     begin 
		              gcd_valid<=1'b0;
		              if(en_test==1'b1)
                       state<=div;
				        else 
				           state<=idle;
					  end 
					  
	    div:      begin 
		              state<=cal;
						  a<=tempa;             
						  b<=tempb;
					  end 
       cal:      begin 
		              if(yushu==8'b0000_0000)
						     state<=out;
						  else 
						     begin 
							  a<=b;
							  b<=yushu;
							  state<=cal; 
							  end 
					  end  
		 out:      begin
		               state<=idle;
							gcd<=b;
							gcd_valid<=1'b1;
					  end 
		 default:  state<=idle;
	endcase
   end 	
end 

div_cal #(.width(8)) inst(.a(a), .b(b),.shang(shang),.yushu(yushu)); 
endmodule 
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值