New CPU multiplier
authorlekernel <sebastien.bourdeauducq@lekernel.net>
Thu, 24 Jun 2010 15:51:36 +0000 (17:51 +0200)
committerlekernel <sebastien.bourdeauducq@lekernel.net>
Thu, 24 Jun 2010 15:51:36 +0000 (17:51 +0200)
boards/milkymist-one/rtl/ddram.v
boards/milkymist-one/rtl/lm32_include.v
boards/milkymist-one/rtl/system.v
boards/milkymist-one/rtl/vga.v
boards/milkymist-one/sources.mak
cores/lm32/rtl/lm32_multiplier_spartan6.v [new file with mode: 0644]

index 36aabd1..60599ee 100644 (file)
@@ -133,11 +133,11 @@ DCM_SP #(
        .PSDONE(psdone),
        .PSCLK(sys_clk)
 );
-AUTOBUF b1(
+BUFG b1(
        .I(dqs_clk_dcm),
        .O(dqs_clk)
 );
-AUTOBUF b2(
+BUFG b2(
        .I(dqs_clk_n_dcm),
        .O(dqs_clk_n)
 );
index c789da6..982e907 100644 (file)
@@ -40,8 +40,7 @@
 `define CFG_EBA_RESET 32'h0
 `define CFG_DEBA_RESET 32'h0
 
-// FIXME: temporarily using MC multiplier because PL does not meet timing
-`define CFG_MC_MULTIPLY_ENABLED
+`define CFG_PL_MULTIPLY_ENABLED
 `define CFG_PL_BARREL_SHIFT_ENABLED
 `define CFG_SIGN_EXTEND_ENABLED
 `define CFG_MC_DIVIDE_ENABLED
index 9f2a38a..eb5527b 100644 (file)
@@ -182,11 +182,11 @@ DCM_SP #(
        .RST(1'b0),
        .PSEN(1'b0)
 );
-AUTOBUF b1(
+BUFG b1(
        .I(sys_clk_dcm),
        .O(sys_clk)
 );
-AUTOBUF b2(
+BUFG b2(
        .I(sys_clk_n_dcm),
        .O(sys_clk_n)
 );
index ecddecf..821ef4e 100644 (file)
@@ -92,11 +92,11 @@ DCM_SP #(
 
        .PSEN(1'b0)
 );
-AUTOBUF b_p(
+BUFG b_p(
        .I(vga_iclk_dcm),
        .O(vga_iclk)
 );
-AUTOBUF b_n(
+BUFG b_n(
        .I(vga_iclk_n_dcm),
        .O(vga_iclk_n)
 );
index be3abef..a63076e 100644 (file)
@@ -2,21 +2,21 @@ BOARD_SRC=$(wildcard $(BOARD_DIR)/*.v) $(BOARD_DIR)/../../gen_capabilities.v
 
 ASFIFO_SRC=$(wildcard $(CORES_DIR)/asfifo/rtl/*.v)
 CONBUS_SRC=$(wildcard $(CORES_DIR)/conbus/rtl/*.v)
-LM32_SRC=                                              \
-       $(CORES_DIR)/lm32/rtl/lm32_cpu.v                \
-       $(CORES_DIR)/lm32/rtl/lm32_instruction_unit.v   \
-       $(CORES_DIR)/lm32/rtl/lm32_decoder.v            \
-       $(CORES_DIR)/lm32/rtl/lm32_load_store_unit.v    \
-       $(CORES_DIR)/lm32/rtl/lm32_adder.v              \
-       $(CORES_DIR)/lm32/rtl/lm32_addsub.v             \
-       $(CORES_DIR)/lm32/rtl/lm32_logic_op.v           \
-       $(CORES_DIR)/lm32/rtl/lm32_shifter.v            \
-       $(CORES_DIR)/lm32/rtl/lm32_multiplier.v         \
-       $(CORES_DIR)/lm32/rtl/lm32_mc_arithmetic.v      \
-       $(CORES_DIR)/lm32/rtl/lm32_interrupt.v          \
-       $(CORES_DIR)/lm32/rtl/lm32_ram.v                \
-       $(CORES_DIR)/lm32/rtl/lm32_icache.v             \
-       $(CORES_DIR)/lm32/rtl/lm32_dcache.v             \
+LM32_SRC=                                                      \
+       $(CORES_DIR)/lm32/rtl/lm32_cpu.v                        \
+       $(CORES_DIR)/lm32/rtl/lm32_instruction_unit.v           \
+       $(CORES_DIR)/lm32/rtl/lm32_decoder.v                    \
+       $(CORES_DIR)/lm32/rtl/lm32_load_store_unit.v            \
+       $(CORES_DIR)/lm32/rtl/lm32_adder.v                      \
+       $(CORES_DIR)/lm32/rtl/lm32_addsub.v                     \
+       $(CORES_DIR)/lm32/rtl/lm32_logic_op.v                   \
+       $(CORES_DIR)/lm32/rtl/lm32_shifter.v                    \
+       $(CORES_DIR)/lm32/rtl/lm32_multiplier_spartan6.v        \
+       $(CORES_DIR)/lm32/rtl/lm32_mc_arithmetic.v              \
+       $(CORES_DIR)/lm32/rtl/lm32_interrupt.v                  \
+       $(CORES_DIR)/lm32/rtl/lm32_ram.v                        \
+       $(CORES_DIR)/lm32/rtl/lm32_icache.v                     \
+       $(CORES_DIR)/lm32/rtl/lm32_dcache.v                     \
        $(CORES_DIR)/lm32/rtl/lm32_top.v
 FMLARB_SRC=$(wildcard $(CORES_DIR)/fmlarb/rtl/*.v)
 FMLBRG_SRC=$(wildcard $(CORES_DIR)/fmlbrg/rtl/*.v)
diff --git a/cores/lm32/rtl/lm32_multiplier_spartan6.v b/cores/lm32/rtl/lm32_multiplier_spartan6.v
new file mode 100644 (file)
index 0000000..5d182cd
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Milkymist VJ SoC
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+module lm32_multiplier(
+       input clk_i,
+       input rst_i,
+       input stall_x,
+       input stall_m,
+       input [31:0] operand_0,
+       input [31:0] operand_1,
+       output [31:0] result
+);
+
+// See UG389, esp. p. 29 "Fully Pipelined, 35 x 35 Multiplier Use Model (Large Multiplier)"
+
+wire [17:0] au = {3'd0, operand_0[31:17]};
+wire [17:0] al = {1'b0, operand_0[16:0]};
+wire [17:0] bu = {3'd0, operand_1[31:17]};
+wire [17:0] bl = {1'b0, operand_1[16:0]};
+
+wire [17:0] bl_forward;
+wire [35:0] al_bl;
+
+reg [16:0] result_low;
+always @(posedge clk_i) begin
+       if(rst_i)
+               result_low <= 17'd0;
+       else
+               result_low <= al_bl[16:0];
+end
+assign result[16:0] = result_low;
+
+DSP48A1 #(
+       .A0REG(1),
+       .A1REG(0),
+       .B0REG(1),
+       .B1REG(0),
+       .CARRYINREG(0),
+       .CARRYINSEL("OPMODE5"),
+       .CARRYOUTREG(0),
+       .CREG(0),
+       .DREG(0),
+       .MREG(1),
+       .OPMODEREG(0),
+       .PREG(0),
+       .RSTTYPE("SYNC")
+) D1 (
+       .BCOUT(bl_forward),
+       .PCOUT(),
+       .CARRYOUT(),
+       .CARRYOUTF(),
+       .M(al_bl),
+       .P(),
+       .PCIN(),
+       .CLK(clk_i),
+       .OPMODE(8'd1),
+       .A(al),
+       .B(bl),
+       .C(),
+       .CARRYIN(),
+       .D(),
+       .CEA(~stall_x),
+       .CEB(~stall_x),
+       .CEC(),
+       .CECARRYIN(),
+       .CED(),
+       .CEM(~stall_m),
+       .CEOPMODE(),
+       .CEP(1'b1),
+       .RSTA(rst_i),
+       .RSTB(rst_i),
+       .RSTC(),
+       .RSTCARRYIN(),
+       .RSTD(),
+       .RSTM(rst_i),
+       .RSTOPMODE(),
+       .RSTP()
+);
+
+wire [47:0] au_bl_sum;
+
+DSP48A1 #(
+       .A0REG(1),
+       .A1REG(0),
+       .B0REG(0),
+       .B1REG(0),
+       .CARRYINREG(0),
+       .CARRYINSEL("OPMODE5"),
+       .CARRYOUTREG(0),
+       .CREG(0),
+       .DREG(0),
+       .MREG(1),
+       .OPMODEREG(0),
+       .PREG(0),
+       .RSTTYPE("SYNC")
+) D2 (
+       .BCOUT(),
+       .PCOUT(au_bl_sum),
+       .CARRYOUT(),
+       .CARRYOUTF(),
+       .M(),
+       .P(),
+       .PCIN(),
+       .CLK(clk_i),
+       .OPMODE(8'd13),
+       .A(au),
+       .B(bl_forward),
+       .C({31'd0, al_bl[33:17]}),
+       .CARRYIN(),
+       .D(),
+       .CEA(~stall_x),
+       .CEB(),
+       .CEC(),
+       .CECARRYIN(),
+       .CED(),
+       .CEM(~stall_m),
+       .CEOPMODE(),
+       .CEP(),
+       .RSTA(rst_i),
+       .RSTB(),
+       .RSTC(),
+       .RSTCARRYIN(),
+       .RSTD(),
+       .RSTM(rst_i),
+       .RSTOPMODE(),
+       .RSTP()
+);
+
+wire [47:0] r_full;
+assign result[31:17] = r_full[31:17];
+
+DSP48A1 #(
+       .A0REG(1),
+       .A1REG(0),
+       .B0REG(1),
+       .B1REG(0),
+       .CARRYINREG(0),
+       .CARRYINSEL("OPMODE5"),
+       .CARRYOUTREG(0),
+       .CREG(0),
+       .DREG(0),
+       .MREG(1),
+       .OPMODEREG(0),
+       .PREG(1),
+       .RSTTYPE("SYNC")
+) D3 (
+       .BCOUT(),
+       .PCOUT(),
+       .CARRYOUT(),
+       .CARRYOUTF(),
+       .M(),
+       .P(r_full),
+       .PCIN(au_bl_sum),
+       .CLK(clk_i),
+       .OPMODE(8'd5),
+       .A(bu),
+       .B(al),
+       .C(),
+       .CARRYIN(),
+       .D(),
+       .CEA(~stall_x),
+       .CEB(~stall_x),
+       .CEC(),
+       .CECARRYIN(),
+       .CED(),
+       .CEM(~stall_m),
+       .CEOPMODE(),
+       .CEP(1'b1),
+       .RSTA(rst_i),
+       .RSTB(rst_i),
+       .RSTC(),
+       .RSTCARRYIN(),
+       .RSTD(),
+       .RSTM(rst_i),
+       .RSTOPMODE(),
+       .RSTP(rst_i)
+);
+
+endmodule