解题思路:

       题目要求求解两个数的最小公倍数,而最小公倍数可以通过两个数的乘积除以两个数的最小公约数得到。乘法是容易计算的,所以问题变成如何求解最大公约数。可以采用辗转相减法求解,例如 :两个自然数35和14,用大数减去小数,(35,14)->(21,14)->(7,14),此时,7小于14,要做一次交换,把14作为被减数,即(14,7)->(7,7),再做一次相减,结果为0,这样也就求出了最大公约数7。

       然后可以实现除法器IP核或者之间使用 ‘/’进行除法运算得到最小公倍数,‘/’在多数的编译器中也可以进行综合。

解题过程:

       在模块声明时,定义输入数据的位宽

module lcm#(

parameter DATA_W = 8)                   //定位位宽参数,缺省值为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    wire                             vld_out,         //输出数据有效的指示信号

);

       声明一些中间变量,缓存模块允许输入,且输入有效时的a,b的数值。缓存两个乘积的数值和最大公约数求解完成的指示信号。

reg     [DATA_W*2-1:0]   mcd,a_buf,b_buf;

reg     [DATA_W*2-1:0]   mul_buf;

reg                                 mcd_vld;

       使用状态机实现辗转相减法,声明状态变量

reg     [1:0]                     cur_st,nxt_st;

         parameter                IDLE = 2’b00,S0 = 2’b01, S1 = 2’b10, S3 = 2’b11;

       根据辗转相减法的过程,编写状态机:

//两段式状态机

always @(posedge clk or negedge rst_n)

       if (!rst_n)

              cur_st <= IDLE;

       else

              cur_st <= nxt_st;

always @(posedge clk or negedge rst_n)

       if (!rst_n) begin

              nxt_st <= IDLE;

              mcd   <= 0;

              mcd_vld <= 0;

              a_buf <= 0;

              b_buf <= 0;

              mul_buf <= 0;

              vld_out <= 1'b0;

       end

       else begin     

              case (cur_st)

              IDLE:if(vld_in) begin     

                            a_buf <= A;

                            b_buf <= B;

                            nxt_st <= S0;

                            mul_buf <= A*B;

                            mcd_vld <= 0;

                            vld_out <= 1'b0;

                            end

                            else begin

                            nxt_st <= IDLE;

                            mcd_vld <= 0;

                            vld_out <= 1'b0;

                            end

              S0:if(a_buf!=b_buf)begin

                            if(a_buf>b_buf)begin

                                   a_buf<=a_buf-b_buf;

                                   b_buf<=b_buf;

                            end

                            else begin

                                   b_buf <= b_buf - a_buf;

                                   a_buf <= a_buf;

                                   vld_out <= 1'b0;

                            end

                            nxt_st <= S0;

                            end

                            else begin     

                                   nxt_st <=S1;

                                   vld_out <= 1'b0;

                                   end

              S1:begin

                     mcd <= b_buf;

                     mcd_vld <= 1'b1;

                     nxt_st     <= IDLE;

                     vld_out <= 1'b1;

                     end

              default:begin

                     nxt_st<=IDLE;

                     vld_out <= 1'b0;

                     end

              endcase

       end

      

assign mcd_out = mcd;

assign lcm_out = mul_buf/mcd;

endmodule

仿真结果:


参考答案
`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*2-1:0]	mcd,a_buf,b_buf;
reg [DATA_W*2-1:0]	mul_buf;
reg					mcd_vld;
reg	[1:0]			cur_st,nxt_st;
parameter IDLE= 2'b00,S0 = 2'b01, S1 = 2'b10, S2 = 2'b11;
//两段式状态机
always @(posedge clk or negedge rst_n)
	if (!rst_n)
		cur_st <= IDLE;
	else
		cur_st <= nxt_st;
always @(posedge clk or negedge rst_n)
	if (!rst_n) begin
		nxt_st <= IDLE;
		mcd	  <= 0;
		mcd_vld <= 0;
		a_buf <= 0;
		b_buf <= 0;
		mul_buf <= 0;
		vld_out <= 1'b0;
	end
	else begin	
		case (cur_st)
		IDLE:if(vld_in) begin	
				a_buf <= A;
				b_buf <= B;
				nxt_st <= S0;
				mul_buf <= A*B;
				mcd_vld <= 0;
				vld_out <= 1'b0;
				end
				else begin
				nxt_st <= IDLE;
				mcd_vld <= 0;
				vld_out <= 1'b0;
				end
		S0:if(a_buf!=b_buf)begin
				if(a_buf>b_buf)begin
					a_buf<=a_buf-b_buf;
					b_buf<=b_buf;
				end
				else begin 
					b_buf <= b_buf - a_buf;
					a_buf <= a_buf;
					vld_out <= 1'b0;
				end
				nxt_st <= S0;
				end
				else begin	
					nxt_st <=S1;
					vld_out <= 1'b0;
					end
		S1:begin	
			mcd <= b_buf;
			mcd_vld <= 1'b1;
			nxt_st	<= IDLE;
			vld_out <= 1'b1;
			end
		default:begin	
			nxt_st<=IDLE;
			vld_out <= 1'b0;
			end
		endcase
	end
	
assign mcd_out = mcd;
assign lcm_out = mul_buf/mcd;
endmodule


如果关于此次题单有问题或者反馈意见,欢迎加入牛客用户反馈群沟通~