OpenCores
URL https://opencores.org/ocsvn/rf68000/rf68000/trunk

Subversion Repositories rf68000

[/] [rf68000/] [trunk/] [rtl/] [cpu/] [rf68000_divider.v] - Rev 3

Go to most recent revision | Compare with Previous | Blame | View Log

`timescale 1ns / 1ps
// ============================================================================
//        __
//   \\__/ o\    (C) 2013-2022  Robert Finch, Waterloo
//    \  __ /    All rights reserved.
//     \/_//     robfinch<remove>@finitron.ca
//       ||
//
// BSD 3-Clause License
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//                                                                          
// ============================================================================
//
// rf68000_divider.v
//  - 32 bit divider
//
// ============================================================================
//
module rf68000_divider(rst, clk, ld, abort, sgn, sgnus, a, b, qo, ro, dvByZr, ovf, done, idle);
parameter WID=32;
parameter DIV=3'd3;
parameter IDLE=3'd4;
parameter DONE=3'd5;
input clk;
input rst;
input ld;
input abort;
input sgn;
input sgnus;
input [WID-1:0] a;
input [WID-1:0] b;
output [WID-1:0] qo;
reg [WID-1:0] qo;
output [WID-1:0] ro;
reg [WID-1:0] ro;
output done;
output idle;
output dvByZr;
output ovf;
reg dvByZr;
reg ovf;
 
reg [WID-1:0] aa,bb;
reg so, rs;
reg [2:0] state;
reg [7:0] cnt;
wire cnt_done = cnt==8'd0;
assign done = state==DONE||(state==IDLE && !ld);
assign idle = state==IDLE;
reg ce1;
reg [WID-1:0] q;
reg [WID:0] r;
wire b0 = bb <= r;
wire [WID-1:0] r1 = b0 ? r - bb : r;
 
initial begin
  q = 32'd0;
  r = 32'd0;
  qo = 32'd0;
  ro = 32'd0;
end
 
always @(posedge clk)
if (rst) begin
	aa <= {WID{1'b0}};
	bb <= {WID{1'b0}};
	q <= {WID{1'b0}};
	r <= {WID{1'b0}};
	qo <= {WID{1'b0}};
	ro <= {WID{1'b0}};
	cnt <= 8'd0;
	dvByZr <= 1'b0;
	ovf <= 1'b0;
	so <= 1'b0;
	rs <= 1'b0;
	state <= IDLE;
end
else
begin
if (abort)
    cnt <= 8'd00;
else if (!cnt_done)
	cnt <= cnt - 8'd1;
 
case(state)
IDLE:
	if (ld) begin
		ovf <= 1'b0;
		if (sgn) begin
			q <= a[WID-1] ? -a : a;
			bb <= b[WID-1] ? -b : b;
			so <= a[WID-1] ^ b[WID-1];
			rs <= a[WID-1];
		end
		else if (sgnus) begin
			q <= a[WID-1] ? -a : a;
            bb <= b;
            so <= a[WID-1];
		end
		else begin
			q <= a;
			bb <= b;
			so <= 1'b0;
			$display("bb=%d", b);
		end
		dvByZr <= b=={WID{1'b0}};
		r <= {WID{1'b0}};
		cnt <= WID+1;
		state <= DIV;
	end
DIV:
	if (!cnt_done) begin
		$display("cnt:%d r1=%h q[31:0]=%h", cnt,r1,q);
		q <= {q[WID-2:0],b0};
		r <= {r1,q[WID-1]};
		if (q[31:16] >= bb[15:0] && cnt==WID+1) begin
			ovf <= 1'b1;
			state <= DONE;
		end
	end
	else begin
		$display("cnt:%d r1=%h q[63:0]=%h", cnt,r1,q);
		if (sgn|sgnus) begin
			if (so)
				qo <= -q;
			else
				qo <= q;
			// The sign of the remainder is the same as the dividend.
			if (rs != r[WID])
				ro <= -r[WID:1];
			else
				ro <= r[WID:1];
		end
		else begin
			qo <= q;
			ro <= r[WID:1];
		end
		state <= DONE;
	end
DONE:
	begin
		/*
		if (so) begin
			if (qo[WID-1:WID/2] != {WID/2{qo[WID/2-1]}})
				ovf <= 1'b1;
		end
		else begin
			if (qo[WID-1:WID/2] != 'd0)
				ovf <= 1'b1;
		end
		*/
		if (!ld)
			state <= IDLE;
	end
default: state <= IDLE;
endcase
end
 
endmodule
 
module rf68000_divider_tb();
parameter WID=32;
reg rst;
reg clk;
reg ld;
wire done;
wire [WID-1:0] qo,ro;
 
initial begin
	clk = 1;
	rst = 0;
	#100 rst = 1;
	#100 rst = 0;
	#100 ld = 1;
	#150 ld = 0;
end
 
always #10 clk = ~clk;	//  50 MHz
 
 
rf68000_divider #(WID) u1
(
	.rst(rst),
	.clk(clk),
	.ld(ld),
	.abort(1'b0),
	.sgn(1'b0),
	.sgnus(1'b0),
	.a(32'h10000000),
	.b(32'h5a5a),
	.qo(qo),
	.ro(ro),
	.dvByZr(),
	.ovf(),
	.done(done),
	.idle()
);
 
endmodule
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.