赞
踩
module divider#( parameter WIDTH = 8, parameter WIDTH_dout = 16 ) ( input clk, input rst_n, input [WIDTH - 1 : 0] i_a, input [WIDTH - 1 : 0] i_b, input i_vld, output reg o_rdy, output [WIDTH - 1 : 0] o_quotient, output [WIDTH - 1 : 0] o_remainder, output o_vld ); //=====================parameter parameter IDLE = 2'b00; parameter SHIFT = 2'b01; parameter SUB = 2'b10; parameter OUTPUT = 2'b11; //=====================defination reg [1 : 0] state, state_n; reg [WIDTH_dout - 1 : 0] temp_a; reg [WIDTH_dout - 1 : 0] temp_b; reg [2 : 0] cnt; wire add_cnt; wire end_cnt; //=====================output always@(posedge clk or negedge rst_n)begin if(!rst_n) state <= IDLE; else state <= state_n; end always@(*)begin case (state) IDLE : if(i_vld && o_rdy) state_n = SHIFT; SHIFT : state_n = SUB; SUB : if(end_cnt) state_n = OUTPUT; else state_n = SHIFT; OUTPUT : state_n = IDLE; default : state_n = IDLE; endcase end always@(posedge clk or negedge rst_n) begin if(!rst_n) o_rdy <= 1'b1; else if(state == OUTPUT) o_rdy <= 1'b1; else if(i_vld) o_rdy <= 1'b0; end assign add_cnt = (state == SUB); assign end_cnt = add_cnt && (cnt == WIDTH - 1); always@(posedge clk or negedge rst_n)begin if(!rst_n) cnt <= 'd0; else if(end_cnt) cnt <= 'd0; else if(add_cnt) cnt <= cnt + 1'b1; end always@(posedge clk or negedge rst_n)begin if(!rst_n) temp_b <= 'd0; else if(i_vld && o_rdy) temp_b <= {i_b, {(WIDTH){1'b0}}}; end always@(posedge clk or negedge rst_n)begin if(!rst_n) temp_a <= 'd0; else case (state_n) SHIFT : begin if(i_vld && o_rdy) temp_a <= {{(WIDTH - 1){1'b0}}, i_a, 1'b0}; else temp_a <= temp_a << 1; end SUB : if(temp_a >= temp_b) temp_a <= temp_a - temp_b + 1'b1; endcase end assign o_quotient = temp_a[WIDTH - 1 : 0]; assign o_remainder = temp_a[WIDTH_dout - 1 : WIDTH]; assign o_vld = (state == OUTPUT); endmodule
module tb_divider(); //===================parameter parameter PERIOD = 10 / 2; parameter WIDTH = 8; parameter WIDTH_dout = 16; //===================defination reg clk, rst_n; reg [WIDTH - 1 : 0] a; reg [WIDTH - 1 : 0] b; wire [WIDTH - 1 : 0] q; wire [WIDTH - 1 : 0] r; reg i_vld; wire o_rdy; wire o_vld; //===================output initial begin clk = 0; rst_n = 0; #20 rst_n = 1; #1000 $finish; end always #PERIOD clk = ~clk; initial begin i_vld = 0; #50 i_vld = 1; end initial begin a = 0; #50; @(posedge clk) a = 100; #170; @(posedge clk) a = 210; #170; @(posedge clk) a = 50; #170; @(posedge clk) a = 17; end initial begin b = 0; #50; @(posedge clk) b = 100; #170; @(posedge clk) b = 211; #170; @(posedge clk) b = 5; #170; @(posedge clk) b = 3; end divider#( .WIDTH (WIDTH), .WIDTH_dout (WIDTH_dout) ) u_divider ( .clk (clk), .rst_n(rst_n), .i_a(a), .i_b(b), .i_vld(i_vld), .o_rdy(o_rdy), .o_quotient(q), .o_remainder(r), .o_vld(o_vld) ); `ifdef FSDB initial begin $fsdbDumpfile("tb_divider.fsdb"); $fsdbDumpvars; $fsdbDumpMDA(); end `endif endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。