verilog带符号除法器
matlab代码
%divide clear; close all; clc; WIDTH=16; div_A=[20855,21855,15,1166,11665,1115,1180,32777];%WIDTH=16 div_B=[2,2,5,15,123,112,134,129]; for i=1:length(div_A) for j=1:length(div_B) div_rem_d=abs(div_A(i))*2;%高位补div_A位宽-1=(WIDTH-1)个0,低位补1个0;余数初值 div_quo_d=0;%商位宽为WIDTH, div_C(i,j)=0; div_B_d=div_B(j)*2^(WIDTH); for k=1:WIDTH if div_rem_d>=div_B_d div_rem_d=(div_rem_d-div_B_d)*2+1; div_C(i,j)=div_C(i,j)*2+1; else div_rem_d=div_rem_d*2; div_C(i,j)=div_C(i,j)*2; end end div_rem_tmp2=floor(div_rem_d/2^(WIDTH+1)); div_rem(i,j)= div_rem_tmp2; end end
matlab统一按无符号数处理了,修改很简单,就没改
verilog代码
`timescale 1ns / 1ps module divide#(parameter width_A=16, parameter width_B=8 )( input clk, input rst_n, input[width_A-1:0] div_A, //被除数 input[width_B-1:0] div_B, //除数 input valid_in, output reg valid_out, output reg [width_A-1:0] div_C, //商 output reg[width_A-1:0] div_rem //余数,恒为正 ); parameter DIV_IDLE = 2'd0; parameter DIV_BUSY = 2'd1; parameter DIV_DONE = 2'd2; parameter DIV_ACK = 2'd3; reg [1:0] next_state,state; // reg [7:0] result; reg[width_A+width_B-1:0] div_B_d; reg[width_A+width_B-1:0] div_B_d_tmp; reg[2*width_A-1:0] div_rem_d; reg [2*width_A-1:0] div_rem_d_tmp; reg[width_A-1:0] div_quo; reg [width_A-1:0] div_quo_d; reg[3:0] cnt; wire [width_A-1:0] abs_A; wire [width_B-1:0] abs_B; wire [2*width_A-1:0] div_rem_tmp; assign abs_A = div_A[width_A-1] ? ~div_A+1 : div_A; assign abs_B=div_B[width_B-1] ? ~div_B+1 : div_B; assign is_neg = div_A[width_A-1] ^ div_B[width_B-1]; assign all_neg = div_A[width_A-1] & div_B[width_B-1]; always@(*) begin case(state) DIV_IDLE:begin if(valid_in) next_state=DIV_BUSY; else next_state=DIV_IDLE; end DIV_BUSY:begin if(cnt==width_A-1) next_state=DIV_DONE; else next_state=DIV_BUSY; end DIV_DONE:begin next_state=DIV_ACK; end DIV_ACK :begin next_state=DIV_IDLE; end default: next_state=DIV_IDLE; endcase end always@(posedge clk) if(~rst_n) state<=DIV_IDLE; else state<=next_state; always@(posedge clk) if(~rst_n)begin div_B_d<=0;//除数寄存器 div_rem_d<=0;//余数寄存器 // div_quo_d<=0;//商寄存器 div_rem<=0; div_C<=0; cnt<=0; valid_out<=1'b0; end else begin case(state) DIV_IDLE :begin valid_out<=1'b0; if(valid_in)begin div_B_d<={abs_B,{(width_A)1'b0}}; div_rem_d<={{(width_A-1)1'b0},abs_A,1'b0}; // div_quo_d<=0; cnt<=0; end end DIV_BUSY:begin div_rem_d<=div_rem_d_tmp; // div_quo_d<=div_quo; // div_B_d<=div_B_d; cnt<=cnt+1; end DIV_DONE:begin valid_out<=1'b1; if(all_neg) begin //A<0,B<0; div_C<=div_rem_d[width_A-1:0]+1; div_rem<=div_B_d[width_A+width_B-1:width_A]-{0,div_rem_d[2*width_A-1:width_A+1]}; end else if(is_neg) begin //A<0,B>0 // div_C<=~div_quo_d+1; /* div_C<=~div_rem_d[15:0]+1; */ div_C<=~div_rem_d[width_A-1:0]; div_rem<=div_B_d[width_A+width_B-1:width_A]-{0,div_rem_d[2*width_A-1:width_A+1]}; //31:17 end else begin //A>0,B>0 // div_C<=div_quo_d; div_C<=div_rem_d[width_A-1:0]; div_rem<={0,div_rem_d[2*width_A-1:width_A+1]}; end end DIV_ACK: valid_out<=1'b0; endcase end reg data_bit; assign div_rem_tmp=div_rem_d-div_B_d; always@(*)begin if(div_rem_d<div_B_d) begin div_rem_d_tmp={div_rem_d[2*width_A-2:0],1'b0}; data_bit=0; // div_quo={div_quo_d,1'b0}; end else begin div_rem_d_tmp={div_rem_tmp[2*width_A-2:0],1'b1}; // div_quo={div_quo_d,1'b1}; data_bit=1; end // div_B_d_tmp={1'b0,div_B_d[23:1]}; end endmodule
testbench
`timescale 1ns / 1ps // module tb_divide; reg clk; reg rst_n; reg start; reg [15:0]div_A; reg [7:0]div_B; wire done; wire [15:0]div_C; always #10 clk = ~clk; initial begin rst_n = 0; clk = 1; #10; rst_n = 1; end divide u_divide( .clk(clk), .rst_n(rst_n), .div_A(div_A), .div_B(div_B), .valid_in(start), .valid_out(done), .div_C(div_C) ); reg [3:0]i; always @ ( posedge clk or negedge rst_n ) if( !rst_n ) begin i <= 4'd0; start <= 1'b0; div_A<= 16'd1; div_B<= 8'd1; end else begin case( i ) 0: if( done ) begin start <= 1'b0; i <= i + 1'b1; end else begin div_A<= 16'b1101_0101_0101_0101; div_B<= 8'd5; start <= 1'b1; end 1: // if( done ) begin start <= 1'b0; i <= i + 1'b1; end else begin div_A<= 16'd15; div_B<= 8'd5; start <= 1'b1; end 2: // if( done ) begin start <= 1'b0; i <= i + 1'b1; end else begin div_A<= 16'd1166; div_B<= 8'b11111011; //为了实验随手改成了负数 start <= 1'b1; end 3: // if( done ) begin start <= 1'b0; i <= i + 1'b1; end else begin div_A<= 16'd11665; div_B<= 8'd123; start <= 1'b1; end 4: // if( done ) begin start <= 1'b0; i <= i + 1'b1; end else begin div_A<= 16'd11665; div_B<= 8'd1; start <= 1'b1; end 5: // if( done ) begin start <= 1'b0; i <= i + 1'b1; end else begin div_A<= 16'd15; div_B<= 8'd3; start <= 1'b1; end 6: // if( done ) begin start <= 1'b0; i <= i + 1'b1; end else begin div_A<= 16'b1111_1111_1111_0001; //为了实验随手改成了二进制负数 div_B<= 8'b1111_1110; start <= 1'b1; end 7: begin i <= 4'd7; end endcase end endmodule
单纯记录一下

浙公网安备 33010602011771号