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

Subversion Repositories or1k

[/] [or1k/] [tags/] [rel_15/] [or1200/] [rtl/] [verilog/] [or1200_mult_mac.v] - Diff between revs 504 and 1035

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

Rev 504 Rev 1035
Line 8... Line 8...
////  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.        ////
////                                                              ////
////                                                              ////
////  To Do:                                                      ////
////  To Do:                                                      ////
////   - make it smaller and faster                               ////
////   - make signed division better, w/o negating the operands   ////
////                                                              ////
////                                                              ////
////  Author(s):                                                  ////
////  Author(s):                                                  ////
////      - Damjan Lampret, lampret@opencores.org                 ////
////      - Damjan Lampret, lampret@opencores.org                 ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
Line 43... Line 43...
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//
//
// CVS Revision History
// CVS Revision History
//
//
// $Log: not supported by cvs2svn $
// $Log: not supported by cvs2svn $
 
// 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
// 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.
// 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
// Revision 1.2  2001/10/14 13:12:09  lampret
// MP3 version.
// MP3 version.
Line 107... Line 110...
output  [31:0]                   spr_dat_o;
output  [31:0]                   spr_dat_o;
 
 
//
//
// Internal wires and regs
// Internal wires and regs
//
//
wire    [width-1:0]              result;
reg     [width-1:0]              result;
reg     [2*width-1:0]            mul_prod_r;
reg     [2*width-1:0]            mul_prod_r;
reg     [2*width-1:0]            mac_r;
reg     [2*width-1:0]            mac_r;
wire    [2*width-1:0]            mul_prod;
wire    [2*width-1:0]            mul_prod;
wire    [`OR1200_MACOP_WIDTH-1:0]        mac_op;
wire    [`OR1200_MACOP_WIDTH-1:0]        mac_op;
reg     [`OR1200_MACOP_WIDTH-1:0]        mac_op_r1;
reg     [`OR1200_MACOP_WIDTH-1:0]        mac_op_r1;
Line 120... Line 123...
reg                             mac_stall_r;
reg                             mac_stall_r;
wire    [width-1:0]              x;
wire    [width-1:0]              x;
wire    [width-1:0]              y;
wire    [width-1:0]              y;
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;
 
reg                             div_free;
 
`ifdef OR1200_IMPL_DIV
 
wire    [width-1:0]              div_tmp;
 
reg     [5:0]                    div_cntr;
 
`endif
 
 
//
//
// Combinatorial logic
// Combinatorial logic
//
//
assign result = (alu_op == `OR1200_ALUOP_MUL) ? mul_prod_r[31:0] : mac_r[59:28];
 
assign spr_maclo_we = spr_cs & spr_write & spr_addr[`OR1200_MAC_ADDR];
assign spr_maclo_we = spr_cs & spr_write & spr_addr[`OR1200_MAC_ADDR];
assign spr_machi_we = spr_cs & spr_write & !spr_addr[`OR1200_MAC_ADDR];
assign spr_machi_we = spr_cs & spr_write & !spr_addr[`OR1200_MAC_ADDR];
assign spr_dat_o = spr_addr[`OR1200_MAC_ADDR] ? mac_r[31:0] : mac_r[63:32];
assign spr_dat_o = spr_addr[`OR1200_MAC_ADDR] ? mac_r[31:0] : mac_r[63:32];
`ifdef OR1200_LOWPWR_MULT
`ifdef OR1200_LOWPWR_MULT
assign x = (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ? a : 32'h0000_0000;
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 y = (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ? b : 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
 
assign x = alu_op_div & a[31] ? ~a + 1'b1 : a;
 
assign y = alu_op_div & b[31] ? ~b + 1'b1 : b;
 
`endif
 
`ifdef OR1200_IMPL_DIV
 
assign alu_op_div = (alu_op == `OR1200_ALUOP_DIV);
 
assign alu_op_div_divu = alu_op_div | (alu_op == `OR1200_ALUOP_DIVU);
 
assign div_tmp = mul_prod_r[63:32] - y;
`else
`else
assign x = a;
assign alu_op_div = 1'b0;
assign y = b;
assign alu_op_div_divu = 1'b0;
`endif
`endif
 
 
//
//
 
// Select result of current ALU operation to be forwarded
 
// to next instruction and to WB stage
 
//
 
always @(alu_op or mul_prod_r or mac_r or a or b)
 
        casex(alu_op)   // synopsys parallel_case
 
`ifdef OR1200_IMPL_DIV
 
                `OR1200_ALUOP_DIV:
 
                        result = a[31] ^ b[31] ? ~mul_prod_r[31:0] + 1'b1 : mul_prod_r[31:0];
 
                `OR1200_ALUOP_DIVU,
 
`endif
 
                `OR1200_ALUOP_MUL: begin
 
                        result = mul_prod_r[31:0];
 
                end
 
                default:
 
                        result = mac_r[59:28];
 
        endcase
 
 
 
//
// Instantiation of the multiplier
// Instantiation of the multiplier
//
//
`ifdef OR1200_ASIC_MULTP2_32X32
`ifdef OR1200_ASIC_MULTP2_32X32
or1200_amultp2_32x32 or1200_amultp2_32x32(
or1200_amultp2_32x32 or1200_amultp2_32x32(
        .X(x),
        .X(x),
Line 158... Line 193...
        .P(mul_prod)
        .P(mul_prod)
);
);
`endif
`endif
 
 
//
//
// Registered output from the multiplier
// Registered output from the multiplier and
 
// an optional divider
//
//
always @(posedge rst or posedge clk)
always @(posedge rst or posedge clk)
        if (rst)
        if (rst) begin
                mul_prod_r <= #1 64'h0000_0000_0000_0000;
                mul_prod_r <= #1 64'h0000_0000_0000_0000;
 
                div_free <= #1 1'b1;
 
`ifdef OR1200_IMPL_DIV
 
                div_cntr <= #1 6'b00_0000;
 
`endif
 
        end
 
`ifdef OR1200_IMPL_DIV
 
        else if (|div_cntr) begin
 
                if (div_tmp[31])
 
                        mul_prod_r <= #1 {mul_prod_r[62:0], 1'b0};
        else
        else
 
                        mul_prod_r <= #1 {div_tmp[30:0], mul_prod_r[31:0], 1'b1};
 
                div_cntr <= #1 div_cntr - 1'b1;
 
        end
 
        else if (alu_op_div_divu && div_free) begin
 
                mul_prod_r <= #1 {31'b0, x[31:0], 1'b0};
 
                div_cntr <= #1 6'b10_0000;
 
                div_free <= #1 1'b0;
 
        end
 
`endif
 
        else if (div_free | !ex_freeze) begin
                mul_prod_r <= #1 mul_prod[63:0];
                mul_prod_r <= #1 mul_prod[63:0];
 
                div_free <= #1 1'b1;
 
        end
 
 
//
//
// Propagation of l.mac opcode
// Propagation of l.mac opcode
//
//
always @(posedge clk or posedge rst)
always @(posedge clk or posedge rst)
Line 215... Line 272...
                mac_r <= #1 64'h0000_0000_0000_0000;
                mac_r <= #1 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.
//
//
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 1'b0;
        else
        else
                mac_stall_r <= #1 (|mac_op | (|mac_op_r1) | (|mac_op_r2)) & id_macrc_op;
                mac_stall_r <= #1 (|mac_op | (|mac_op_r1) | (|mac_op_r2)) & id_macrc_op
 
`ifdef OR1200_IMPL_DIV
 
                                | (|div_cntr)
 
`endif
 
                                ;
endmodule
endmodule
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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