求最大公约数和最小公倍数

首先可以采用辗转相除法或者相减法求解最大公约数MCD;
然后利用A* B=MCD* LCM,求解最小公倍数;
其中辗转相减法和除法运算可采用状态机的方式实现。
除法部分原理参见前面的博客

module lcm_mcd #(
	parameter DATA = 8 
)(
	input clk,
	input rst_n,
	input [DATA-1:0] A,
	input [DATA-1:0] B,
	input vld_in,
	output wire [DATA*2-1:0] lcm_out,
	output wire [DATA-1:0] mcd_out,
	output wire vld_out,
	output wire readr
);

reg [DATA*2-1:0] mcd,a_buf,b_buf;
reg [DATA*2-1:0] mul_buf;
reg mcd_vld;
reg [1:0] cur_st,nxt_st;

parameter IDLE = 2'b00;
parameter S0 = 2'b01;
parameter S1 = 2'b10;
parameter S2 = 2'b11;


//assign ready = (cur_st==IDLE) ? 1'b1 : 1'b0;
always @ (posedge clk or negedge rst_n) begin
	if(!rst) begin
		cur_st <= IDLE;
	end
	else begin
		cur_st <= nxt_st;
	end
end

always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		nxt_st <= IDLE;
		mcd <= 'd0;
		mcd_vld <= 'd0;
		a_buf <= 'd0;
		b_buf <= 'd0;
		mul_buf <= 'd0;
	end
	else begin
		case(cur_st)
			ILDE : if(vld_in) begin
						a_buf <= A;
						b_buf <= B;
						nxt_st <= S0;
						mul_buf <= A*B;
						mcd  <= 'd0;
						mcd_vld <= 'd0;
				   end
				   else begin
						nxt_st <= IDLE;
						mcd_vld <= 'd0;
				   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;
						end
						nxt_st <= S0;
				  end
				  else begin
						nxt_st <= S1;
				  end
			S1 : begin
					mcd <= b_buf;
					mcd_vld <= 1'b1;
					nxt_st <= IDLE;
				 end
			default : nxt_st <= IDLE;
		endcase
	end
end


div #(
	.DATA(DATA*2)
)div_inst (
		.clk(clk),
		.rst_n(rst_n),
		.vld_in(mcd_vld),
		.ready(ready),
		.dividend(mul_buf),
		.divisor(mcd),
		.quotient(lcm_out),
		.remainder(),
		.vld_out(vld_out)
);



assign mcd_out = mcd;


endmodule

module div #(
parameter DATA = 8
)(
	input clk,
	input rst,
	input vld_in,
	output wire ready,
	input [DATA-1:0] dividend,
	input [DATA-1:0] divisor,
	output wire [DATA-1:0] quotient,
	output wire [DATA-1:0] remainder,
	output wire vld_out
);

reg [DATA*2-1:0] dividend_e;
reg [DATA*2-1:0] divisor_e;
reg [DATA-1:0] quotient;
reg [DATA-1:0] remainder_e;

reg [DATA-1:0] count;
reg [1:0] cur_st,nxt_st;
parameter IDLE = 2'b00,
		  SUB = 2'b01,
		  SHIFT = 2'b10,
		  DONE = 2'b11;

always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		dividend_e <= 'd0;
		divisor_e <= 'd0;
		quotient_e <= 'd0;
		remainder <= 'd0;
		count <= 'd0;
		cur_st <= IDLE;
	end
	else begin
		case(cur_st) 
			IDLE : begin
						dividend_e <= {{DATA{1'b0}},dividend};
						divisor_e <= {divisor,{DATA{1'b0}}};
						if(vld_in) 
							cur_st <= SUB;
						else 
							cur_st <= IDLE;
				   end
			SUB : begin
						if(dividend_e>=divisor_e) begin
							quotiend_e <= {quotiend_e[DATA-2],1'b1};
							dividend_e <= dividend_e - divisor_e;
						end
						else begin
							quotient_e <= {quotient_e[DATA_W-2:0],1'b0};
							dividend_e <= dividend_e;
						end
						cur_st <= SHIFT;
				  end
			SHIFT : begin
						if(count<DATA) begin
							cur_st <= SUB;
							dividend_e <= dividend_e << 1;
							count <= count + 1'b1;
						end
						else begin
							cur_St <= DONE;
							remainder_e <= dividend_e[DATA*2-1:DATA];
						end
					end
			DONE : begin
						count <= 0;
						cur_st <= IDLE;
					end
			default : begin
						count <= 0;
						cur_st <= IDLE;
					end
		endcase
	end
end

assign quotient  = quotient_e;
assign remainder = remainder_e;

assign ready=(cur_st==IDLE)?1'b1:1'b0;
assign vld_out=(cur_st==DONE)?1'b1:1'b0;
endmodule

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值