OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [or1200/] [rtl/] [verilog/] [or1200_mult_mac.v] - Diff between revs 141 and 258

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 141 Rev 258
Line 1... Line 1...
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
////  OR1200's Top level multiplier and MAC                       ////
////  OR1200's Top level multiplier, divider and MAC              ////
////                                                              ////
////                                                              ////
////  This file is part of the OpenRISC 1200 project              ////
////  This file is part of the OpenRISC 1200 project              ////
////  http://www.opencores.org/cores/or1k/                        ////
////  http://opencores.org/project,or1k                           ////
////                                                              ////
////                                                              ////
////  Description                                                 ////
////  Description                                                 ////
////  Multiplier is 32x32 however multiply instructions only      ////
////  Multiplier is 32x32 however multiply instructions only      ////
////  use lower 32 bits of the result. MAC is 32x32=64+64.        ////
////  use lower 32 bits of the result. MAC is 32x32=64+64.        ////
////                                                              ////
////                                                              ////
Line 47... Line 47...
// $Log: or1200_mult_mac.v,v $
// $Log: or1200_mult_mac.v,v $
// Revision 2.0  2010/06/30 11:00:00  ORSoC
// Revision 2.0  2010/06/30 11:00:00  ORSoC
// Minor update: 
// Minor update: 
// Bugs fixed. 
// Bugs fixed. 
//
//
// Revision 1.5  2006/04/09 01:32:29  lampret
 
// See OR1200_MAC_SHIFTBY in or1200_defines.v for explanation of the change. Since now no more 28 bits shift for l.macrc insns however for backward compatbility it is possible to set arbitry number of shifts.
 
//
 
// Revision 1.4  2004/06/08 18:17:36  lampret
 
// Non-functional changes. Coding style fixes.
 
//
 
// Revision 1.3  2003/04/24 00:16:07  lampret
 
// No functional changes. Added defines to disable implementation of multiplier/MAC
 
//
 
// Revision 1.2  2002/09/08 05:52:16  lampret
 
// Added optional l.div/l.divu insns. By default they are disabled.
 
//
 
// Revision 1.1  2002/01/03 08:16:15  lampret
 
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
 
//
 
// Revision 1.3  2001/10/21 17:57:16  lampret
 
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
 
//
 
// Revision 1.2  2001/10/14 13:12:09  lampret
 
// MP3 version.
 
//
 
// Revision 1.1.1.1  2001/10/06 10:18:38  igorm
 
// no message
 
//
 
//
 
 
 
// synopsys translate_off
// synopsys translate_off
`include "timescale.v"
`include "timescale.v"
// synopsys translate_on
// synopsys translate_on
`include "or1200_defines.v"
`include "or1200_defines.v"
Line 155... Line 130...
wire                            spr_maclo_we;
wire                            spr_maclo_we;
wire                            spr_machi_we;
wire                            spr_machi_we;
wire                            alu_op_div_divu;
wire                            alu_op_div_divu;
wire                            alu_op_div;
wire                            alu_op_div;
reg                             div_free;
reg                             div_free;
`ifdef OR1200_IMPL_DIV
`ifdef OR1200_DIV_IMPLEMENTED
wire    [width-1:0]              div_tmp;
wire    [width-1:0]              div_tmp;
reg     [5:0]                    div_cntr;
reg     [5:0]                    div_cntr;
`endif
`endif
 
 
//
//
Line 173... Line 148...
assign spr_maclo_we = 1'b0;
assign spr_maclo_we = 1'b0;
assign spr_machi_we = 1'b0;
assign spr_machi_we = 1'b0;
assign spr_dat_o = 32'h0000_0000;
assign spr_dat_o = 32'h0000_0000;
`endif
`endif
`ifdef OR1200_LOWPWR_MULT
`ifdef OR1200_LOWPWR_MULT
assign x = (alu_op_div & a[31]) ? ~a + 1'b1 : alu_op_div_divu | (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ? a : 32'h0000_0000;
assign x = (alu_op_div & a[31]) ? ~a + 1'b1 :
assign y = (alu_op_div & b[31]) ? ~b + 1'b1 : alu_op_div_divu | (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ? b : 32'h0000_0000;
           alu_op_div_divu | (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ?
 
           a : 32'h0000_0000;
 
assign y = (alu_op_div & b[31]) ? ~b + 1'b1 :
 
           alu_op_div_divu | (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ?
 
           b : 32'h0000_0000;
`else
`else
assign x = alu_op_div & a[31] ? ~a + 32'b1 : a;
assign x = alu_op_div & a[31] ? ~a + 32'b1 : a;
assign y = alu_op_div & b[31] ? ~b + 32'b1 : b;
assign y = alu_op_div & b[31] ? ~b + 32'b1 : b;
`endif
`endif
`ifdef OR1200_IMPL_DIV
`ifdef OR1200_DIV_IMPLEMENTED
assign alu_op_div = (alu_op == `OR1200_ALUOP_DIV);
assign alu_op_div = (alu_op == `OR1200_ALUOP_DIV);
assign alu_op_div_divu = alu_op_div | (alu_op == `OR1200_ALUOP_DIVU);
assign alu_op_div_divu = alu_op_div | (alu_op == `OR1200_ALUOP_DIVU);
assign div_tmp = mul_prod_r[63:32] - y;
assign div_tmp = mul_prod_r[63:32] - y;
`else
`else
assign alu_op_div = 1'b0;
assign alu_op_div = 1'b0;
Line 196... Line 175...
// Select result of current ALU operation to be forwarded
// Select result of current ALU operation to be forwarded
// to next instruction and to WB stage
// to next instruction and to WB stage
//
//
always @(alu_op or mul_prod_r or mac_r or a or b)
always @(alu_op or mul_prod_r or mac_r or a or b)
        casex(alu_op)   // synopsys parallel_case
        casex(alu_op)   // synopsys parallel_case
`ifdef OR1200_IMPL_DIV
 `ifdef OR1200_DIV_IMPLEMENTED
                `OR1200_ALUOP_DIV:
    `OR1200_ALUOP_DIV: begin
                        result = a[31] ^ b[31] ? ~mul_prod_r[31:0] + 1'b1 : mul_prod_r[31:0];
                        result = a[31] ^ b[31] ? ~mul_prod_r[31:0] + 1'b1 : mul_prod_r[31:0];
 
    end
                `OR1200_ALUOP_DIVU,
                `OR1200_ALUOP_DIVU,
`endif
`endif
                `OR1200_ALUOP_MUL: begin
                `OR1200_ALUOP_MUL: begin
                        result = mul_prod_r[31:0];
                        result = mul_prod_r[31:0];
                end
                end
Line 239... Line 219...
// Registered output from the multiplier and
// Registered output from the multiplier and
// an optional divider
// an optional divider
//
//
always @(posedge rst or posedge clk)
always @(posedge rst or posedge clk)
        if (rst) begin
        if (rst) begin
                mul_prod_r <= #1 64'h0000_0000_0000_0000;
                mul_prod_r <=  64'h0000_0000_0000_0000;
                div_free <= #1 1'b1;
                div_free <=  1'b1;
`ifdef OR1200_IMPL_DIV
`ifdef OR1200_DIV_IMPLEMENTED
                div_cntr <= #1 6'b00_0000;
                div_cntr <=  6'b00_0000;
`endif
`endif
        end
        end
`ifdef OR1200_IMPL_DIV
`ifdef OR1200_DIV_IMPLEMENTED
        else if (|div_cntr) begin
        else if (|div_cntr) begin
                if (div_tmp[31])
                if (div_tmp[31])
                        mul_prod_r <= #1 {mul_prod_r[62:0], 1'b0};
                        mul_prod_r <=  {mul_prod_r[62:0], 1'b0};
                else
                else
                        mul_prod_r <= #1 {div_tmp[30:0], mul_prod_r[31:0], 1'b1};
                        mul_prod_r <=  {div_tmp[30:0], mul_prod_r[31:0], 1'b1};
                div_cntr <= #1 div_cntr - 1'b1;
                div_cntr <=  div_cntr - 1'b1;
        end
        end
        else if (alu_op_div_divu && div_free) begin
        else if (alu_op_div_divu && div_free) begin
                mul_prod_r <= #1 {31'b0, x[31:0], 1'b0};
                mul_prod_r <=  {31'b0, x[31:0], 1'b0};
                div_cntr <= #1 6'b10_0000;
                div_cntr <=  6'b10_0000;
                div_free <= #1 1'b0;
                div_free <=  1'b0;
        end
        end
`endif // OR1200_IMPL_DIV
`endif // OR1200_DIV_IMPLEMENTED
        else if (div_free | !ex_freeze) begin
        else if (div_free | !ex_freeze) begin
                mul_prod_r <= #1 mul_prod[63:0];
                mul_prod_r <=  mul_prod[63:0];
                div_free <= #1 1'b1;
                div_free <=  1'b1;
        end
        end
 
 
`else // OR1200_MULT_IMPLEMENTED
`else // OR1200_MULT_IMPLEMENTED
assign result = {width{1'b0}};
assign result = {width{1'b0}};
assign mul_prod = {2*width{1'b0}};
assign mul_prod = {2*width{1'b0}};
Line 277... Line 257...
//
//
// Propagation of l.mac opcode
// Propagation of l.mac opcode
//
//
always @(posedge clk or posedge rst)
always @(posedge clk or posedge rst)
        if (rst)
        if (rst)
                mac_op_r1 <= #1 `OR1200_MACOP_WIDTH'b0;
                mac_op_r1 <=  `OR1200_MACOP_WIDTH'b0;
        else
        else
                mac_op_r1 <= #1 mac_op;
                mac_op_r1 <=  mac_op;
 
 
//
//
// Propagation of l.mac opcode
// Propagation of l.mac opcode
//
//
always @(posedge clk or posedge rst)
always @(posedge clk or posedge rst)
        if (rst)
        if (rst)
                mac_op_r2 <= #1 `OR1200_MACOP_WIDTH'b0;
                mac_op_r2 <=  `OR1200_MACOP_WIDTH'b0;
        else
        else
                mac_op_r2 <= #1 mac_op_r1;
                mac_op_r2 <=  mac_op_r1;
 
 
//
//
// Propagation of l.mac opcode
// Propagation of l.mac opcode
//
//
always @(posedge clk or posedge rst)
always @(posedge clk or posedge rst)
        if (rst)
        if (rst)
                mac_op_r3 <= #1 `OR1200_MACOP_WIDTH'b0;
                mac_op_r3 <=  `OR1200_MACOP_WIDTH'b0;
        else
        else
                mac_op_r3 <= #1 mac_op_r2;
                mac_op_r3 <=  mac_op_r2;
 
 
//
//
// Implementation of MAC
// Implementation of MAC
//
//
always @(posedge rst or posedge clk)
always @(posedge rst or posedge clk)
        if (rst)
        if (rst)
                mac_r <= #1 64'h0000_0000_0000_0000;
                mac_r <=  64'h0000_0000_0000_0000;
`ifdef OR1200_MAC_SPR_WE
`ifdef OR1200_MAC_SPR_WE
        else if (spr_maclo_we)
        else if (spr_maclo_we)
                mac_r[31:0] <= #1 spr_dat_i;
                mac_r[31:0] <=  spr_dat_i;
        else if (spr_machi_we)
        else if (spr_machi_we)
                mac_r[63:32] <= #1 spr_dat_i;
                mac_r[63:32] <=  spr_dat_i;
`endif
`endif
        else if (mac_op_r3 == `OR1200_MACOP_MAC)
        else if (mac_op_r3 == `OR1200_MACOP_MAC)
                mac_r <= #1 mac_r + mul_prod_r;
                mac_r <=  mac_r + mul_prod_r;
        else if (mac_op_r3 == `OR1200_MACOP_MSB)
        else if (mac_op_r3 == `OR1200_MACOP_MSB)
                mac_r <= #1 mac_r - mul_prod_r;
                mac_r <=  mac_r - mul_prod_r;
        else if (macrc_op && !ex_freeze)
        else if (macrc_op && !ex_freeze)
                mac_r <= #1 64'h0000_0000_0000_0000;
                mac_r <=  64'h0000_0000_0000_0000;
 
 
//
//
// Stall CPU if l.macrc is in ID and MAC still has to process l.mac instructions
// Stall CPU if l.macrc is in ID and MAC still has to process l.mac instructions
// in EX stage (e.g. inside multiplier)
// in EX stage (e.g. inside multiplier)
// This stall signal is also used by the divider.
// This stall signal is also used by the divider.
//
//
always @(posedge rst or posedge clk)
always @(posedge rst or posedge clk)
        if (rst)
        if (rst)
                mac_stall_r <= #1 1'b0;
                mac_stall_r <=  1'b0;
        else
        else
                mac_stall_r <= #1 (|mac_op | (|mac_op_r1) | (|mac_op_r2)) & (id_macrc_op | mac_stall_r)
                mac_stall_r <=  (|mac_op | (|mac_op_r1) | (|mac_op_r2)) & (id_macrc_op | mac_stall_r)
`ifdef OR1200_IMPL_DIV
`ifdef OR1200_DIV_IMPLEMENTED
                                | (|div_cntr)
                                | (|div_cntr)
`endif
`endif
                                ;
                                ;
`else // OR1200_MAC_IMPLEMENTED
`else // OR1200_MAC_IMPLEMENTED
assign mac_stall_r = 1'b0;
assign mac_stall_r = 1'b0;

powered by: WebSVN 2.1.0

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