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

Subversion Repositories hive

[/] [hive/] [trunk/] [v01.09/] [alu_mult_shift.v] - Rev 4

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

/*
--------------------------------------------------------------------------------
 
Module : alu_mult_shift
 
--------------------------------------------------------------------------------
 
Function:
- Multiply & shift unit for a processor ALU.
 
Instantiates:
- functions.h (clog2)
- (1x) alu_multiply.v
  - (1x) vector_sr.v (debug mode only)
- (3x) vector_sr.v
 
Notes:
- I/O optionally registered.
- 5 stage pipeline w/ 4 mid registers (not counting I/O registering).
- Shift left signed uses signed B to shift signed A left (B+) and right (B-).
- Shift left unsigned and B(0,+) gives 2^B (one-hot / power of 2).
- Shift left unsigned and B(-) gives unsigned A shift right.
- Shift takes precedence over multiply.
- Copy takes precedence over shift & multiply.
- Copy unsigned & signed unextended results s/b the same.
- Copy unsigned extended result s/b all zero.
- Copy signed extended result s/b all B sign.
- Debug mode for comparison to native signed multiplication, only use for 
  simulation as it consumes resources and negatively impacts top speed. 
 
--------------------------------------------------------------------------------
*/
 
module alu_mult_shift
	#(
	parameter	integer							REGS_IN			= 1,		// in register option
	parameter	integer							REGS_OUT			= 1,		// out register option
	parameter	integer							DATA_W			= 4,		// data width
	parameter	integer							DEBUG_MODE		= 1		// 1=debug mode; 0=normal mode
	)
	(
	// clocks & resets
	input			wire								clk_i,						// clock
	input			wire								rst_i,						// async. reset, active high
	// control I/O
	input			wire								sgn_i,						// 1=signed
	input			wire								ext_i,						// 1=extended result
	input			wire								shl_i,						// 1=shift left
	input			wire								cpy_i,						// 1=copy b
	// data I/O
	input			wire	[DATA_W-1:0]			a_i,							// operand
	input			wire	[DATA_W-1:0]			b_i,							// operand
	output		wire	[DATA_W-1:0]			result_o,					// result
	// debug
	output		wire								debug_o						// 1=bad match
	);
 
 
	/*
	----------------------
	-- internal signals --
	----------------------
	*/
	`include "functions.h"  // for clog2()
	localparam	integer							SH_SEL_W			= clog2( DATA_W );
	localparam	integer							ZSX_W				= DATA_W+1;  // +1 extra bit
	localparam	integer							DBL_W				= DATA_W*2;  // double width
	//
	wire					[DATA_W-1:0]			a, b;
	wire												cpy, shl, ext, sgn;
	reg					[DATA_W:0]				a_mux, b_mux;  // +1 extra bit
	reg												ext_mux;
	wire												ext_mux_r;
	wire					[DBL_W-1:0]				res_dbl;
	reg					[DATA_W-1:0]			result;
 
 
	/*
	================
	== code start ==
	================
	*/
 
 
	// optional input regs
	vector_sr
	#(
	.REGS			( REGS_IN ),
	.DATA_W		( DATA_W+DATA_W+4 ),
	.RESET_VAL	( 0 )
	)
	in_regs
	(
	.clk_i		( clk_i ),
	.rst_i		( rst_i ),
	.data_i		( { a_i, b_i, cpy_i, shl_i, ext_i, sgn_i } ),
	.data_o		( { a,   b,   cpy,   shl,   ext,   sgn } )
	);
 
 
	// mux inputs and extended result selector
	always @ ( * ) begin
		casex ( { cpy, shl, sgn } )
			'b000 : begin  // unsigned multiply
				a_mux <= a;  // zero extend
				b_mux <= b;  // zero extend
				ext_mux <= ext;  // follow input
			end
			'b001 : begin  // signed multiply
				a_mux <= { a[DATA_W-1], a };  // sign extend
				b_mux <= { b[DATA_W-1], b };  // sign extend
				ext_mux <= ext;  // follow input
			end
			'b010 : begin  // unsigned shift / pow2
				a_mux <= ( b[DATA_W-1] ) ? a : 1'b1;  // a=1 for positive shifts
				b_mux <= 1'b1 << b[SH_SEL_W-1:0];  // pow2
				ext_mux <= b[DATA_W-1];  // sign selects output
			end
			'b011 : begin  // signed shift
				a_mux <= { a[DATA_W-1], a };  // sign extend
				b_mux <= 1'b1 << b[SH_SEL_W-1:0];  // pow2
				ext_mux <= b[DATA_W-1];  // sign selects output
			end
			'b1x0 : begin  // unsigned copy b
				a_mux <= 1'b1;  // a=1
				b_mux <= b;  // zero extend
				ext_mux <= ext;  // follow input
			end
			'b1x1 : begin  // signed copy b
				a_mux <= 1'b1;  // a=1
				b_mux <= { b[DATA_W-1], b };  // sign extend
				ext_mux <= ext;  // follow input
			end
		endcase
	end
 
 
	// signed multiplier (4 registers deep)
	alu_multiply
	#(
	.DATA_W			( ZSX_W ),
	.DEBUG_MODE		( DEBUG_MODE )
	)
	alu_multiply
	(
	.clk_i			( clk_i ),
	.rst_i			( rst_i ),
	.a_i				( a_mux ),
	.b_i				( b_mux ),
	.result_o		( res_dbl ),
	.debug_o			( debug_o )
	);
 
 
	// pipeline extended result selector to match multiply
	vector_sr
	#(
	.REGS			( 4 ),
	.DATA_W		( 1 ),
	.RESET_VAL	( 0 )
	)
	regs_ext
	(
	.clk_i		( clk_i ),
	.rst_i		( rst_i ),
	.data_i		( ext_mux ),
	.data_o		( ext_mux_r )
	);
 
 
	// multiplex
	always @ ( * ) begin
		case ( ext_mux_r )
			'b0 : result <= res_dbl[DATA_W-1:0];
			'b1 : result <= res_dbl[DBL_W-1:DATA_W];
		endcase
	end
 
 
	// optional output regs
	vector_sr
	#(
	.REGS			( REGS_OUT ),
	.DATA_W		( DATA_W ),
	.RESET_VAL	( 0 )
	)
	out_regs
	(
	.clk_i		( clk_i ),
	.rst_i		( rst_i ),
	.data_i		( result ),
	.data_o		( result_o )
	);
 
 
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.