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

Subversion Repositories or1k

[/] [or1k/] [branches/] [mp3_stable/] [or1200/] [rtl/] [verilog/] [alu.v] - Rev 161

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

//////////////////////////////////////////////////////////////////////
////                                                              ////
////  OR1200's ALU                                                ////
////                                                              ////
////  This file is part of the OpenRISC 1200 project              ////
////  http://www.opencores.org/cores/or1k/                        ////
////                                                              ////
////  Description                                                 ////
////  ALU                                                         ////
////                                                              ////
////  To Do:                                                      ////
////   - make it smaller and faster                               ////
////                                                              ////
////  Author(s):                                                  ////
////      - Damjan Lampret, lampret@opencores.org                 ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2000 Authors and OPENCORES.ORG                 ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
//
 
`include "alu_defs.h"
`include "general.h"
`include "or32isa.h"
 
module alu(clk, rst, a, b, alu_op, shrot_op, comp_op, result, flag);
 
parameter width = `OPERAND_WIDTH;
 
input clk;
input rst;
input [width-1:0] a;
input [width-1:0] b;
input [`ALUOP_WIDTH-1:0] alu_op;
input [`SHROTOP_WIDTH-1:0] shrot_op;
input [`COMPOP_WIDTH-1:0] comp_op;
output [width-1:0] result;
output flag;
 
reg [width-1:0] result;
reg [width-1:0] shifted_rotated;
reg flagforw;
reg flag_we;
reg flag;
reg [width-1:0] mul_prod;
 
integer d1;
integer d2;
 
wire [width-1:0] comp_a;
wire [width-1:0] comp_b;
wire a_eq_b;
wire a_lt_b;
wire [width-1:0] mul_a;
wire [width-1:0] mul_b;
wire [2*width-1:0] tmp_prod;
 
assign comp_a = {a[width-1] ^ comp_op[3] , a[width-2:0]};
assign comp_b = {b[width-1] ^ comp_op[3] , b[width-2:0]};
assign a_eq_b = (comp_a == comp_b);
assign a_lt_b = (comp_a < comp_b);
assign mul_a = a;
assign mul_b = b;
 
// synopsys translate_off
always @(result) begin
	if (result === 32'bx)
		$display("%t: WARNING: 32'bx detected on ALU result bus. Please check !", $time);
end
// synopsys translate_on
 
always @(alu_op or a or b or shifted_rotated or mul_prod) begin
	casex (alu_op)		// synopsys parallel_case full_case
		`ALUOP_SHROT : begin 
				result <= #1 shifted_rotated;
				flag_we <= #1 1'b0;
		end
		`ALUOP_ADD : begin
				result <= #1 a + b;
				flag_we <= #1 1'b0;
		end
		`ALUOP_SUB : begin
				result <= #1 a - b;
				flag_we <= #1 1'b0;
		end
		`ALUOP_XOR : begin
				result <= #1 a ^ b;
				flag_we <= #1 1'b0;
		end
		`ALUOP_OR  : begin
				result <= #1 a | b;
				flag_we <= #1 1'b0;
		end
		`ALUOP_AND : begin
				result <= #1 a & b;
				flag_we <= #1 1'b0;
		end
		`ALUOP_IMM : begin
				result <= #1 b;
				flag_we <= #1 1'b0;
		end
		`ALUOP_MOVHI : begin
				result <= #1 b << 16;
				flag_we <= #1 1'b0;
		end
		`ALUOP_MUL : begin
				result <= #1 mul_prod;
				$display("%t: MUL operation: %h * %h = %h", $time, a, b, mul_prod);
				flag_we <= #1 1'b0;
		end
// synopsys translate_off
		`ALUOP_DIV : begin
				d1 = a;
				d2 = b;
				$display("DIV operation: %d / %d = %d", d1, d2, d1/d2);
				result <= #1 d1 / d2;
				flag_we <= #1 1'b0;
		end
		`ALUOP_DIVU : begin
				result <= #1 a / b;
				flag_we <= #1 1'b0;
		end
// synopsys translate_on
		`ALUOP_COMP: begin
				flag_we <= #1 1'b1;
				result <= #1 32'd0;
		end
	endcase
end
 
always @(shrot_op or a or b) begin
	case (shrot_op)		// synopsys parallel_case full_case
		`SHROTOP_SLL :
				shifted_rotated <= #1 (a << b[4:0]);
		`SHROTOP_SRL :
				shifted_rotated <= #1 (a >> b[4:0]);
		`SHROTOP_SRA :
				shifted_rotated <= #1 ({32{a[31]}} << (5'd32-b[4:0])) | a >> b[4:0];
		`SHROTOP_ROR :
				shifted_rotated <= #1 (a << (5'd32-b[4:0])) | (a >> b[4:0]);
	endcase
end
 
/*
always @(comp_op or a_eq_b or a_lt_b) begin
	case(comp_op[2:0])	// synopsys parallel_case full_case
		`COP_SFEQ:
			flagforw <= #1 a_eq_b;
		`COP_SFNE:
			flagforw <= #1 ~a_eq_b;
		`COP_SFGT:
			flagforw <= #1 ~(a_eq_b | a_lt_b);
		`COP_SFGE:
			flagforw <= #1 ~a_lt_b;
		`COP_SFLT:
			flagforw <= #1 a_lt_b;
		`COP_SFLE:
			flagforw <= #1 a_eq_b | a_lt_b;
// synopsys translate_off
		default:
			flagforw <= #1 1'bx;
// synopsys translate_on
	endcase
end
*/	// alternative (lets check which one is better for DC)
 
always @(comp_op or a_eq_b or a_lt_b or comp_a or comp_b) begin
	case(comp_op[2:0])	// synopsys parallel_case full_case
		`COP_SFEQ:
			flagforw <= #1 (comp_a == comp_b);
		`COP_SFNE:
			flagforw <= #1 (comp_a != comp_b);
		`COP_SFGT:
			flagforw <= #1 (comp_a > comp_b);
		`COP_SFGE:
			flagforw <= #1 (comp_a >= comp_b);
		`COP_SFLT:
			flagforw <= #1 (comp_a < comp_b);
		`COP_SFLE:
			flagforw <= #1 (comp_a <= comp_b);
// synopsys translate_off
		default:
			flagforw <= #1 1'bx;
// synopsys translate_on
	endcase
end
 
 
always @(posedge clk or posedge rst) begin
	if (rst)
		flag <= #1 1'b0;
	else if (flag_we) begin
		$display("COMPARE: comp_a:%h comp_b:%h a_eq_b=%b a_lt_b=%b", comp_a, comp_b, a_eq_b, a_lt_b);
		flag <= #1 flagforw;
	end
end
 
// Instantiation of multiplier
multp2_32x32 multp2_32x32(
	.X(mul_a),
	.Y(mul_b),
	.CLK(clk),
	.P(tmp_prod)
);
 
always @(posedge rst or posedge clk)
	if (rst)
		mul_prod <= #1 32'b0;
	else
		mul_prod <= #1 tmp_prod[31:0];
//		mul_prod <= #1 mul_a[31:0];
 
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.