verilog更相减损法求最小公倍数

verilog更相减损法求最小公倍数

  • 一道有趣的面试题
  • 算法实现原理
    • 传统除法器设计原理
    • RTL级电路
    • verilog code
    • testbench
    • 仿真结果

一道有趣的面试题

博主在技术交流群里,无意看到某公司的一道关于IC的设计题,题目大概的意思就是求两个8位无符号位的最小公倍数。而且要求面积尽可能小。最后要求是用时序电路设计。
博主觉得有趣就做做看,面积尽量小的话博主觉得尽量少用除法器,乘法器。针对求最小公倍数我国古人智慧中就有,在九章算术中提到一种更相减损法,原文这样说

可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之

感谢祖先。另外古希腊欧几里得发现的 “辗转相除法” 同样可以求得最小公倍数。考虑到面积最小,博主就选择了祖先的智慧了,有兴趣的同志可以研究一下辗转相除法。

算法实现原理

在此之前,博主多句嘴,其实在实际中除法,乘法都可以用加法来表示,程序中的减法依然能够转换为加法实现。博主拿减法来解释一下,除法就是一个递减的过程,直到被除数小于除数,得到结果,反之乘法器则是一个累加器。

传统除法器设计原理

传统除法器设计原理

  • 1.先取除数与被除数的正负关系,然后正值化被除数。传统除法器因为需要递减关系,所以除数取负值和补码形式。
  • 2 被除数递减除数,每一次的递减,商数递增。
  • 3 直到被除数小于除数,递减过程剩下的是余数。
  • 4 输出的结果根据除数和被除数的正负关系
    根据题目要求我们不需要进行正值化,首先就是要比较输入大小,以后每次都要比较一次,具体思路看代码。

RTL级电路

RTL级电路结构如图
verilog更相减损法求最小公倍数_第1张图片

verilog code

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: zahngsy
// 
// Create Date: 2019/09/04 14:52:05
// Design Name: 
// Module Name: txt
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module LCM(
															input clk,
															input rst,
															input isStart,
															input [7:0] Data_A,Data_B,
															output reg done,
															output  [15:0] LCM
														);
reg [3:0] i;


reg [7:0] div;
reg [15:0]LCM_r;
reg[7:0] Max,Sec,Thr;
always @(posedge clk )
	if(rst)
		begin
			Max <= 8'd0;
			Sec <= 8'd0;
			Thr <= 8'd0;
			LCM_r<=16'd0;
			i <= 4'd0;
			div <= 8'd0;
			done <=0;
		end
		else if(isStart)
		 case(i)
				0:  
				begin
					if(Data_A > Data_B)
						begin
							Max <= Data_A;
							Sec <= Data_B;
							i <= i+1'b1;
						end 
					else if(Data_A < Data_B)
									begin
										Max <= Data_B;
										Sec <= Data_A;
										i <= i+1'b1;
									end 
					 else i <= 4'd5;//if(Data_A==Data_B)i<=4'd5;
				end
				1:
					begin
						Thr <= Max-Sec; 	
						i <= i +1'b1;
					end
				2:
					if(Thr == Sec)
						i <= 4'd6;
					else if(Thr>Sec)
						i <= i + 1'b1;
					else if(Thr

testbench

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: zhangsy
// 
// Create Date: 2019/09/04 14:52:05
// Design Name: 
// Module Name: txt
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module txt();
reg [7:0] Data_A;
reg [7:0] Data_B;
reg clk,rst,isStart;
wire done;
wire [15:0] LCM;
reg [3:0]i;
initial
begin
clk =0;
rst = 1;
//isStart =0;
#100
rst=0;
//isStart =1;
//#20
 //   Data_A =67;
 //   Data_B=132;
   // #200
 //   Data_A =4;
 //   Data_B=3;
end
always #10 clk = ~clk;
always @ (posedge clk)
    if(rst)
        begin
            isStart <= 0;
            Data_A<= 0;
            Data_B<= 0;
            i <= 0;
        end
     else case(i)
            0:
                if(done) 
                    begin
                       isStart <= 0;
                       i <= i +1'b1;
                    end
                 else
                    begin
                        isStart <= 1;
                        Data_A<= 67;//素数
                        Data_B<= 132;
                    end
             1:
                 if(done) 
                     begin
                        isStart <= 0;
                        i <= i +1'b1;
                     end
                  else
                     begin
                         isStart <= 1;
                         Data_A<= 14;//素数
                         Data_B<= 56;
                     end
            2:
                 if(done) 
                     begin
                        isStart <= 0;
                        i <= i +1'b1;
                     end
                  else
                     begin
                         isStart <= 1;
                         Data_A<= 67;//素数
                         Data_B<= 67;
                     end    
           endcase
                
LCM LCM_inst(
														.clk,
														.rst,
														.isStart,
														.Data_A,
														.Data_B,
														.done,
														.LCM
														);
endmodule

仿真结果

verilog更相减损法求最小公倍数_第2张图片
细心的同志会发现,最后一次输出没有输出done信号,博主后续修改了程序,解决了问题,博主懒得截图就没在从新截图了。实际仿真不会再出现这个问题。
后续博主用三段式状态机写了一个具体参考点这里

你可能感兴趣的:(verilog,FPGA)