verilog实现计算最大公约数和最小公倍数

设计一个时序电路,输入2个无符号数,位宽可以通过参数DATA_W确定,输出这两个数的最小公倍数和最大公约数。

解:在求解最大公约数与最小公倍数时,通常使用辗转相除法计算得到最大公约数,然后利用两数之积除最大公约数得到最小公倍数;

举例如下:

34 与 20;

(1)34 - 20 = 14;

(2)20 - 14 = 6;

(3)14 - 6 = 8;

(4)8 - 6 =2;

(5)6 - 2 = 4;

(6)4 - 2 = 2;

(7)2 - 2 = 0;

所以最大公约数为2;

则最小公倍数 = 34 * 20 /2 =340;

实现代码如下:

`timescale 1ns/1ns

module lcm#(
parameter DATA_W = 8)
(
input [DATA_W-1:0] A,
input [DATA_W-1:0] B,
input 			vld_in,
input			rst_n,
input 			clk,
output	wire	[DATA_W*2-1:0] 	lcm_out,
output	wire 	[DATA_W-1:0]	mcd_out,
output	reg					vld_out
);
    reg       [DATA_W-1:0]       A_reg;
    reg       [DATA_W-1:0]       B_reg;
    reg       [DATA_W*2-1:0]	 lcm  ;
    reg       [DATA_W*2-1:0]     lcm_reg;
    reg       [DATA_W-1:0]	     mcd_reg;
    reg       [1:0]        state;
    parameter            IDLE = 2'b00;
    parameter            st_1 = 2'b01;
    parameter            st_2 = 2'b10;
    
    always@(posedge clk or negedge rst_n)
        if(rst_n == 1'b0)
            begin
                vld_out<= 1'b0;
                A_reg <= 'd0;
                B_reg <= 'd0;
                lcm   <= 'd0;
                mcd_reg <= 'd0;
                lcm_reg <= 'd0;
                state <= IDLE;
            end
    else case(state)
        IDLE:
             begin
                  vld_out <= 1'b0;
                  if(vld_in == 1'b1)
                      begin
                          A_reg <= A;
                          B_reg <= B;
                          lcm_reg<= A*B;
                          state <= st_1;
                      end
                  else
                      begin
                          A_reg <= A_reg;
                          B_reg <= B_reg;
                          lcm_reg<= lcm_reg;
                          state <= IDLE;
                      end
             end
        st_1:
            if(A_reg == B_reg)
                state <= st_2;
            else
                begin
                   state <= st_1;
                   if(A_reg > B_reg)
                        A_reg <= A_reg - B_reg;
                   else if(A_reg < B_reg)
                        B_reg <= B_reg - A_reg;
                end
        st_2:
            begin
                vld_out <= 1'b1;
                lcm <= lcm_reg;
                mcd_reg   <= A_reg;
                state <= IDLE;
            end
    endcase
        
    assign         lcm_out = lcm / mcd_reg;
    assign         mcd_out = mcd_reg;
      
endmodule

仿真代码如下:

`timescale 1ns/1ns

module tb_lcm();

parameter     DATA_W = 8;

reg [DATA_W-1:0] A;
reg [DATA_W-1:0] B;
reg 			 vld_in;
reg			     rst_n;
reg 			 clk;

wire	[DATA_W*2-1:0] 	lcm_out;
wire 	[DATA_W-1:0]	mcd_out;
wire					vld_out;

initial
    begin
	    A <= 'd0;
		B <= 'd0;
		vld_in <= 1'b0;
		rst_n <= 1'b0;
		clk = 1'b0;
		#10
		rst_n <= 1'b1;
        A <= 'd6;
		B <= 'd7;
		vld_in <= 1'b1;
		#2000
		A <= 'd12;
		B <= 'd8;
		vld_in <= 1'b1;
		#1000
		A <= 'd15;
		B <= 'd20;
		vld_in <= 1'b1;
	end

always #10 clk = ~clk;

lcm 
#(
 .DATA_W (DATA_W)
 )
 lcm_u
(
    .A       (A      ),
    .B       (B      ),
    .vld_in  (vld_in ),
    .rst_n   (rst_n  ),
    .clk     (clk    ),
	
    .lcm_out (lcm_out),
    .mcd_out (mcd_out),
    .vld_out (vld_out)
);

endmodule

波形如下:

 

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值