3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-10-06 16:01:57 +00:00

Add first draft of functional SB_MAC16 model

Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
Clifford Wolf 2019-02-19 13:42:21 +01:00
parent 5a853ed46c
commit 62493c91b2
4 changed files with 467 additions and 53 deletions

View file

@ -886,59 +886,6 @@ module SB_WARMBOOT (
);
endmodule
// UltraPlus feature cells
(* blackbox *)
module SB_MAC16 (
input CLK,
input CE,
input [15:0] C,
input [15:0] A,
input [15:0] B,
input [15:0] D,
input AHOLD,
input BHOLD,
input CHOLD,
input DHOLD,
input IRSTTOP,
input IRSTBOT,
input ORSTTOP,
input ORSTBOT,
input OLOADTOP,
input OLOADBOT,
input ADDSUBTOP,
input ADDSUBBOT,
input OHOLDTOP,
input OHOLDBOT,
input CI,
input ACCUMCI,
input SIGNEXTIN,
output [31:0] O,
output CO,
output ACCUMCO,
output SIGNEXTOUT
);
parameter NEG_TRIGGER = 1'b0;
parameter C_REG = 1'b0;
parameter A_REG = 1'b0;
parameter B_REG = 1'b0;
parameter D_REG = 1'b0;
parameter TOP_8x8_MULT_REG = 1'b0;
parameter BOT_8x8_MULT_REG = 1'b0;
parameter PIPELINE_16x16_MULT_REG1 = 1'b0;
parameter PIPELINE_16x16_MULT_REG2 = 1'b0;
parameter TOPOUTPUT_SELECT = 2'b00;
parameter TOPADDSUB_LOWERINPUT = 2'b00;
parameter TOPADDSUB_UPPERINPUT = 1'b0;
parameter TOPADDSUB_CARRYSELECT = 2'b00;
parameter BOTOUTPUT_SELECT = 2'b00;
parameter BOTADDSUB_LOWERINPUT = 2'b00;
parameter BOTADDSUB_UPPERINPUT = 1'b0;
parameter BOTADDSUB_CARRYSELECT = 2'b00;
parameter MODE_8x8 = 1'b0;
parameter A_SIGNED = 1'b0;
parameter B_SIGNED = 1'b0;
endmodule
module SB_SPRAM256KA (
input [13:0] ADDRESS,
input [15:0] DATAIN,
@ -1273,3 +1220,178 @@ module SB_IO_OD (
endgenerate
`endif
endmodule
module SB_MAC16 (
input CLK, CE,
input [15:0] C, A, B, D,
input AHOLD, BHOLD, CHOLD, DHOLD,
input IRSTTOP, IRSTBOT,
input ORSTTOP, ORSTBOT,
input OLOADTOP, OLOADBOT,
input ADDSUBTOP, ADDSUBBOT,
input OHOLDTOP, OHOLDBOT,
input CI, ACCUMCI, SIGNEXTIN,
output [31:0] O,
output CO, ACCUMCO, SIGNEXTOUT
);
parameter [0:0] NEG_TRIGGER = 0;
parameter [0:0] C_REG = 0;
parameter [0:0] A_REG = 0;
parameter [0:0] B_REG = 0;
parameter [0:0] D_REG = 0;
parameter [0:0] TOP_8x8_MULT_REG = 0;
parameter [0:0] BOT_8x8_MULT_REG = 0;
parameter [0:0] PIPELINE_16x16_MULT_REG1 = 0;
parameter [0:0] PIPELINE_16x16_MULT_REG2 = 0;
parameter [1:0] TOPOUTPUT_SELECT = 0;
parameter [1:0] TOPADDSUB_LOWERINPUT = 0;
parameter [0:0] TOPADDSUB_UPPERINPUT = 0;
parameter [1:0] TOPADDSUB_CARRYSELECT = 0;
parameter [1:0] BOTOUTPUT_SELECT = 0;
parameter [1:0] BOTADDSUB_LOWERINPUT = 0;
parameter [0:0] BOTADDSUB_UPPERINPUT = 0;
parameter [1:0] BOTADDSUB_CARRYSELECT = 0;
parameter [0:0] MODE_8x8 = 0;
parameter [0:0] A_SIGNED = 0;
parameter [0:0] B_SIGNED = 0;
wire clock = CLK ^ NEG_TRIGGER;
// internal wires, compare Figure on page 133 of ICE Technology Library 3.0 and Fig 2 on page 2 of Lattice TN1295-DSP
// http://www.latticesemi.com/~/media/LatticeSemi/Documents/TechnicalBriefs/SBTICETechnologyLibrary201608.pdf
// https://www.latticesemi.com/-/media/LatticeSemi/Documents/ApplicationNotes/AD/DSPFunctionUsageGuideforICE40Devices.ashx
wire [15:0] iA, iB, iC, iD;
wire [15:0] iF, iJ, iK, iG;
wire [31:0] iL, iH;
wire [15:0] iW, iX, iP, iQ;
wire [15:0] iY, iZ, iR, iS;
wire HCI, LCI, LCO;
// Regs C and A
reg [15:0] rC, rA;
always @(posedge clock, posedge IRSTTOP) begin
if (IRSTTOP) begin
rC <= 0;
rA <= 0;
end else if (CE) begin
if (!CHOLD) rC <= C;
if (!AHOLD) rA <= A;
end
end
assign iC = C_REG ? rC : C;
assign iA = A_REG ? rA : A;
// Regs B and D
reg [15:0] rB, rD;
always @(posedge clock, posedge IRSTTOP) begin
if (IRSTBOT) begin
rB <= 0;
rD <= 0;
end else if (CE) begin
if (!BHOLD) rB <= B;
if (!DHOLD) rD <= D;
end
end
assign iB = B_REG ? rB : B;
assign iD = D_REG ? rD : D;
// Multiplier Stage
wire [15:0] p_Ah_Bh, p_Al_Bh, p_Ah_Bl, p_Al_Bl;
wire [15:0] Ah, Al, Bh, Bl;
assign Ah = A_SIGNED ? {{8{iA[15]}}, iA[15: 8]} : iA[15: 8];
assign Al = A_SIGNED ? {{8{iA[ 7]}}, iA[ 7: 0]} : iA[15: 8];
assign Bh = B_SIGNED ? {{8{iB[15]}}, iB[15: 8]} : iB[15: 8];
assign Bl = B_SIGNED ? {{8{iB[ 7]}}, iB[ 7: 0]} : iB[15: 8];
assign p_Ah_Bh = Ah * Bh;
assign p_Al_Bh = Al * Bh;
assign p_Ah_Bl = Ah * Bl;
assign p_Al_Bl = Al * Bl;
// Regs F and J
reg [15:0] rF, rJ;
always @(posedge clock, posedge IRSTTOP) begin
if (IRSTTOP) begin
rF <= 0;
rJ <= 0;
end else if (CE) begin
rF <= p_Ah_Bh;
if (!MODE_8x8) rJ <= p_Al_Bh;
end
end
assign iF = TOP_8x8_MULT_REG ? rF : p_Ah_Bh;
assign iJ = PIPELINE_16x16_MULT_REG1 ? rJ : p_Al_Bh;
// Regs K and G
reg [15:0] rK, rG;
always @(posedge clock, posedge IRSTBOT) begin
if (IRSTBOT) begin
rK <= 0;
rG <= 0;
end else if (CE) begin
if (!MODE_8x8) rK <= p_Ah_Bl;
rG <= p_Al_Bl;
end
end
assign iK = PIPELINE_16x16_MULT_REG1 ? rK : p_Ah_Bl;
assign iG = BOT_8x8_MULT_REG ? rG : p_Al_Bl;
// Adder Stage
reg [31:0] P;
always @* begin
P = iG[7:0];
P = P + (iG[15:8] + iK[7:0]) << 8;
P = P + (iK[15:8] + iJ[7:0]) << 16;
P = P + (iJ[15:8] + iF[7:0]) << 24;
end
assign iL = P;
// Reg H
reg [15:0] rH;
always @(posedge clock, posedge IRSTBOT) begin
if (IRSTBOT) begin
rH <= 0;
end else if (CE) begin
if (!MODE_8x8) rH <= iL;
end
end
assign iH = PIPELINE_16x16_MULT_REG2 ? rH : iL;
// Hi Output Stage
wire [15:0] XW, Oh;
reg [15:0] rQ;
assign iW = TOPADDSUB_UPPERINPUT ? iC : iQ[31:16];
assign iX = (TOPADDSUB_LOWERINPUT == 0) ? iA : (TOPADDSUB_LOWERINPUT == 1) ? iF : (TOPADDSUB_LOWERINPUT == 2) ? iH[31:16] : {16{iZ[15]}};
assign {ACCUMCO, XW} = iX + (iW ^ {16{ADDSUBTOP}}) + HCI;
assign CO = ACCUMCO ^ ADDSUBTOP;
assign iP = OLOADTOP ? iC : XW ^ {16{ADDSUBTOP}};
always @(posedge clock, posedge ORSTTOP) begin
if (ORSTTOP) begin
rQ <= 0;
end else if (CE) begin
if (!OHOLDTOP) rQ <= iP;
end
end
assign iQ = rQ;
assign Oh = (TOPOUTPUT_SELECT == 0) ? iP : (TOPOUTPUT_SELECT == 1) ? iQ : (TOPOUTPUT_SELECT == 2) ? iF : iH[31:16];
assign HCI = (TOPADDSUB_CARRYSELECT == 0) ? 1'b0 : (TOPADDSUB_CARRYSELECT == 1) ? 1'b1 : (TOPADDSUB_CARRYSELECT == 2) ? LCO : LCO ^ ADDSUBBOT;
assign SIGNEXTOUT = iX[15];
// Lo Output Stage
wire [15:0] YZ, Ol;
reg [15:0] rS;
assign iY = BOTADDSUB_UPPERINPUT ? iD : iQ[15:0];
assign iZ = (BOTADDSUB_LOWERINPUT == 0) ? iB : (BOTADDSUB_LOWERINPUT == 1) ? iG : (BOTADDSUB_LOWERINPUT == 2) ? iH[15:0] : {16{SIGNEXTIN}};
assign {LCO, YZ} = iZ + (iY ^ {16{ADDSUBBOT}}) + LCI;
assign iR = OLOADBOT ? iD : YZ ^ {16{ADDSUBBOT}};
always @(posedge clock, posedge ORSTBOT) begin
if (ORSTBOT) begin
rS <= 0;
end else if (CE) begin
if (!OHOLDTOP) rS <= iR;
end
end
assign iS = rS;
assign Ol = (BOTOUTPUT_SELECT == 0) ? iR : (BOTOUTPUT_SELECT == 1) ? iS : (BOTOUTPUT_SELECT == 2) ? iG : iH[15:0];
assign LCI = (BOTADDSUB_CARRYSELECT == 0) ? 1'b0 : (BOTADDSUB_CARRYSELECT == 1) ? 1'b1 : (BOTADDSUB_CARRYSELECT == 2) ? ACCUMCI : CI;
assign O = {Oh, Ol};
endmodule