Verilog实现流水线除法器

原本想先写一个非流水线的,写了一点发现花的时间好像不比流水线少多少,还费事,就直接写了流水线的

//A_LEN表示外部模块的接入的被除数宽度,可以不是有效长度
//A_LEN表示外部模块的接入的除数宽度,可以不是有效长度
//因为两个的长度都不是有效长度,所以商最大可能和被除数位宽一样,就弄宽一点
module Divider #(
	parameter		A_LEN = 8,
	parameter		B_LEN = 4)(
	input								CLK,						// 时钟信号
	input								RSTN,                // 复位信号,低有效
	input								EN,                  // 输入数据有效,使能信号
	input [A_LEN-1:0]				Dividend,				//被除数
	input	[B_LEN-1:0]				Divisor,					//除数
	
	output [A_LEN-1:0]			Quotient,				//商
	output [B_LEN-1:0]			Mod,						//余
	output							RDY);
	
	wire [A_LEN-1:0]				Quotient_reg		[A_LEN-1:0];
	wire [B_LEN-1:0] 				Mod_reg				[A_LEN-1:0];
	wire [A_LEN-1:0]				Dividend_ini_reg	[A_LEN-1:0];
	wire [A_LEN-1:0]				rdy;
	wire [B_LEN-1:0]				Divisor_reg			[A_LEN-1:0];
	
	// 初始化第一个Div_cell模块,处理最初的被除数和除数
	Div_cell	#(.A_LEN(A_LEN),.B_LEN(B_LEN))	Divider(
		.CLK(CLK),
		.RSTN(RSTN),
		.EN(EN),
		.Dividend({{(B_LEN){1'b0}}, Dividend[A_LEN-1]}),		// 将被除数的最高位与0拼接
		.Divisor(Divisor),	
		.Dividend_i(Dividend),
		.Quotient_i('b0),

		.Quotient(Quotient_reg[A_LEN-1]),
		.Mod(Mod_reg[A_LEN-1]),		
		.Dividend_o(Dividend_ini_reg[A_LEN-1]),
		.Divisor_o(Divisor_reg[A_LEN-1]),
		.RDY(rdy[A_LEN-1])
		);
	
	// 生成多个Div_cell模块,构成流水线计算结构
	genvar i;
	
	generate 
		for(i=A_LEN-2;i>=0;i=i-1) begin : Div_flow_loop
			Div_cell	#(.A_LEN(A_LEN),.B_LEN(B_LEN))	Divider(
				.CLK(CLK),
				.RSTN(RSTN),
				.EN(rdy[i+1]),
				.Dividend({Mod_reg[i+1], Dividend_ini_reg[i+1][i]}),	// 当前余数与下一个被除数位拼接
				.Divisor(Divisor_reg[i+1]),	
				.Dividend_i(Dividend_ini_reg[i+1]),
				.Quotient_i(Quotient_reg[i+1]),
		
				.Quotient(Quotient_reg[i]),
				.Mod(Mod_reg[i]),		
				.Dividend_o(Dividend_ini_reg[i]),
				.Divisor_o(Divisor_reg[i]),
				.RDY(rdy[i])
				);	
		end
	endgenerate
	
	assign RDY=rdy[0];
	assign Quotient = Quotient_reg[0];
	assign Mod = Mod_reg[0]; 
	
endmodule


module Div_cell#(
	parameter						A_LEN = 8,
	parameter						B_LEN = 4
	)(
	input											CLK,						// 时钟信号
	input											RSTN,						// 复位信号,低有效
	input											EN,						// 输入数据有效,使能信号
	input [B_LEN:0]							Dividend,				//被除数,由上一级传递的余数加上外部模块拼接的原始被除数的下一位
	input	[B_LEN-1:0]							Divisor,					//上一级传递的除数
	input [A_LEN-1:0]							Dividend_i,				//原始被除数
	input [A_LEN-1:0]							Quotient_i,				//上一级传递的商
	
	output reg [A_LEN-1:0]					Quotient,				//商,传递到下一级
	output reg [B_LEN-1:0]					Mod,						//余,也是下一级的被除数
	output reg [A_LEN-1:0]					Dividend_o,				//原始被除数
	output reg [B_LEN-1:0]					Divisor_o,				//原始除数								
	output reg									RDY);
	
	always @(posedge CLK or negedge RSTN) begin
		if(!RSTN) begin													// 异步复位,清零所有寄存器
			Quotient <=	'b0;
			Mod <= 'b0;	
			Dividend_o <= 'b0;
			Divisor_o <= 'b0;
			RDY <= 'b0;	
		end else if(EN) begin											// 当使能信号有效时,进行除法运算
			RDY <= 1'b1;
			Dividend_o <= Dividend_i;
			Divisor_o <= Divisor;
			if(Dividend>={1'b0,Divisor}) begin						// 当前被除数大于等于除数时,商加1,余数更新
				Quotient <= (Quotient_i<<1)+1'b1;
				Mod <= Dividend-{1'b0,Divisor};
			end else begin																
				Quotient <= (Quotient_i<<1)+1'b0;					// 当前被除数小于除数时,商不变,余数不变
				Mod <= Dividend;
			end
		end else begin														// 当使能信号无效时,清零所有寄存器
			Quotient <=	'b0;
			Mod <= 'b0;	
			Dividend_o <= 'b0;
			Divisor_o <= 'b0;
			RDY <= 'b0;
		end
	end
	
endmodule

下面是test bench,有点简陋,见谅

`timescale 1 ns/ 1 ns
module test;
reg 				clk;
reg				en;
reg				rstn;
reg[7:0]			dividend;
reg[3:0]			divisor;

wire [7:0]		quotient;
wire [3:0]		mod;
wire				rdy;

	initial begin
		forever begin
			clk = 1;
			#10;
			clk = 0;
			#10;
		end
	end
	
	integer i;
	initial begin
		i = 0;
		rstn = 1'b1;
		rstn = 1'b0;
		#5;
		rstn = 1'b1;
		
	end
	
	always @(posedge clk) begin
		if(rstn&&!rdy) begin
			case(i)
				0 : begin
					en <= 1'b1;
					dividend <= 8'd34;
					divisor <= 4'd10;
					i = i + 1;
				end
				1 : begin
					dividend <= 8'd10;
					divisor <= 4'd10;
					i = i + 1;
				end
				2 : begin
					dividend <= 8'd100;
					divisor <= 4'd1;
					i = i + 1;
				end
				3 : begin
					dividend <= 8'd34;
					divisor <= 4'd7;
					i = i + 1;
				end
			endcase
		end
	end
	
	Divider 			My_Div(
		.CLK(clk),
		.EN(en),
		.RSTN(rstn),
		.Dividend(dividend),
		.Divisor(divisor),
		.Quotient(quotient),
		.Mod(mod),
		.RDY(rdy));
	
	
	initial begin
		forever begin
			#100
			if($time >= 1000) $finish;
		end
	end
	
endmodule

  • 16
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 流水线除法器是一种用于实现除法操作的电路。它能将一个除数和一个被除数作为输入,并产生商和余数作为输出。下面是使用Verilog语言实现流水线除法器的步骤: 1. 首先,根据除法运算的原理,我们需要将被除数和除数换算成二进制形式,以便进行位运算。 2. 然后,我们需要设计一个控制单元,用于控制流水线的操作。控制单元需要根据被除数和除数的位数,确定流水线的阶段数量。 3. 接下来,我们需要设计具体的流水线阶段。每个阶段负责执行部分除法运算,并将结果传递给下一个阶段。例如,第一阶段可以将被除数右移,以便将该位与除数进行比较。 4. 在每个阶段中,我们需要设计具体的数学运算电路,例如减法器、比较器等,以便执行除法运算的各个步骤。 5. 最后,我们需要将各个阶段连接起来,形成一个完整的流水线除法器电路。在Verilog中,我们可以使用连续赋值语句和模块实例化语句来实现这个连接过程。 总结:流水线除法器Verilog实现主要包括将被除数和除数换算成二进制形式、设计控制单元、设计各个流水线阶段及运算电路,最后将各个阶段连接起来。这样实现流水线除法器能够快速而有效地执行除法运算。 ### 回答2: 流水线除法器Verilog实现可以分为四个阶段:准备阶段、除法阶段、乘法阶段和完成阶段。 在准备阶段,我们需要对输入的被除数和除数进行处理,并初始化一些控制信号和寄存器。首先,我们需要将被除数和除数从输入信号中取出,并进行符号扩展。同时,初始化一些控制信号,如是否为负数等。其次,我们需要对各个寄存器进行初始化,如用于存储商的寄存器、余数寄存器和计数器等。 在除法阶段,我们需要进行真正的除法运算。首先,我们需要通过移位操作将被除数和除数对齐。然后,进行循环操作,每次判断是否可以进行除法运算。如果可以,则进行除法运算,并将商和余数更新到相应的寄存器中。同时,更新计数器的值,以便下一次循环。如果不可以进行除法运算,则跳转到乘法阶段。 在乘法阶段,我们需要实现除数的乘法操作。首先,我们需要对除数进行符号调整,保证除数为正数。然后,通过移位和加法操作,进行乘法运算,并将乘积保存到相应的寄存器中。同时,将计数器的值减一,以便回到除法阶段。 在完成阶段,我们需要进行一些必要的后处理操作。首先,判断商和余数的符号是否需要调整回去。如果需要,则进行相应的调整。然后,将商和余数通过输出信号的形式输出出来。 需要注意的是,流水线除法器Verilog实现是比较复杂的,需要对各个模块进行合理的划分,并进行适当的协调和控制。同时,我们也需要考虑一些特殊情况的处理,如除数为零的情况等。因此,对于初学者而言,需要具备一定的Verilog编程和数字电路设计的知识基础。 ### 回答3: 流水线除法器Verilog实现是一个基于处理器设计的数学计算组件,用于执行除法操作。它通常包括几个关键的部分,如寄存器、控制逻辑、算术单元和时序控制。 在Verilog中,我们可以使用一系列模块和信号来实现流水线除法器。首先,我们需要定义输入和输出信号,包括被除数、除数和商等。然后,我们可以用寄存器模块来存储和更新这些信号的值。 然后,我们需要实现控制逻辑来决定何时执行除法操作。这可以使用有限状态机实现,根据不同的状态决定执行何种操作。例如,我们可以使用状态机来控制加载操作数、执行除法和输出结果等。 接下来,我们需要实现算术单元来进行除法计算。这可以使用一系列乘法、减法和移位操作来实现。具体来说,我们可以使用移位寄存器来对被除数和除数进行移位,并结合减法器来执行除法计算。 最后,我们需要进行时序控制来确保各个模块和信号之间的同步。这可以使用时钟、使能信号和延时器等来实现。 总体而言,流水线除法器Verilog实现是一个复杂的过程,需要对处理器设计、控制逻辑和算术计算有深入的了解。通过编写模块、使用信号和实现适当的逻辑来实现除法操作,我们可以构建一个高效和可靠的流水线除法器

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值