基础004_V7-DSP Slice
主要参考ug479.pdf。之前的文章:FIR调用DSP48E_05。本文主要记录基本用法。
一、DSP48核
A-参数说明
- instrctions,多个功能,通过sel选用
目前没发现C勾选与否,有何影响。
如上图所示,结果3拍后输出:
其他参数:
B-IP调用
生成IP核,参数设置完毕直接调用即可
dsp48_ex dsp_inst( .CLK(clk), .A(a), .B(b), .C(c), .P(p) );
二、原语示例
主要参考pg148-dsp48 macro.pdf用到再细化补充。
Ex1:
// m = b * (a + d)
// p = c+m or p+m
`timescale 1ns / 1ps // m = b * (a + d) // p = c+m or p+m module dsp48_wrap_f ( input clock, input ce1, input ce2, input cem, input cep, input signed [24:0] a, input signed [17:0] b, input signed [47:0] c, input signed [24:0] d, // this has two fewer pipe stages // X+Y is usually the multiplier output (M) // Z is either P, PCIN or C // bit 1:0: 0: Z+X+Y 3:Z-(X+Y) 1: -Z + (X+Y) 2: -1*(Z+X+Y+1) // bits 3:2, 0: Z=0, 1: Z=PCIN, 2: Z=P, 3: Z = C // bit 4: sub in pre add input [4:0] mode, input signed [47:0] pcin, output signed [47:0] pcout, output signed [47-S:0] p); parameter S = 0; parameter USE_DPORT = "FALSE"; // enabling adds 1 reg to A path parameter AREG = 1; parameter BREG = 1; // 0 - 2 wire signed [47:0] dsp_p; assign p = dsp_p[47:S]; DSP48E1 #( .A_INPUT("DIRECT"), // "DIRECT" "CASCADE" .B_INPUT("DIRECT"), // "DIRECT" "CASCADE" .USE_DPORT(USE_DPORT), .USE_MULT("MULTIPLY"),// "MULTIPLY" "DYNAMIC" "NONE" .USE_SIMD("ONE48"), // "ONE48" "TWO24" "FOUR12" // pattern detector - not used .AUTORESET_PATDET("NO_RESET"), .MASK(48'h3fffffffffff), .PATTERN(48'h000000000000), .SEL_MASK("MASK"), .SEL_PATTERN("PATTERN"), .USE_PATTERN_DETECT("NO_PATDET"), // register enables .ACASCREG(1), // pipeline stages between A/ACIN and ACOUT (0, 1 or 2) .ADREG(1), // pipeline stages for pre-adder (0 or 1) .ALUMODEREG(1), // pipeline stages for ALUMODE (0 or 1) .AREG(AREG), // pipeline stages for A (0, 1 or 2) .BCASCREG(1), // pipeline stages between B/BCIN and BCOUT (0, 1 or 2) .BREG(BREG), // pipeline stages for B (0, 1 or 2) .CARRYINREG(1), // this and below are 0 or 1 .CARRYINSELREG(1), .CREG(1), .DREG(1), .INMODEREG(1), .MREG(1), .OPMODEREG(1), .PREG(1)) dsp48_i ( // status .OVERFLOW(), .PATTERNDETECT(), .PATTERNBDETECT(), .UNDERFLOW(), // outs .CARRYOUT(), .P(dsp_p), // control .ALUMODE({2'd0, mode[1:0]}), .CARRYINSEL(3'd0), .CLK(clock), .INMODE({1'b0,mode[4],3'b100}), .OPMODE({1'b0,mode[3:2],4'b0101}), // signal inputs .A({5'd0,a}), // 30 .B(b), // 18 .C(c), // 48 .CARRYIN(1'b0), .D(d), // 25 // cascade ports .ACOUT(), .BCOUT(), .CARRYCASCOUT(), .MULTSIGNOUT(), .PCOUT(pcout), .ACIN(30'h0), .BCIN(18'h0), .CARRYCASCIN(1'b0), .MULTSIGNIN(1'b0), .PCIN(pcin), // clock enables .CEA1(ce1), .CEA2(ce2), .CEAD(1'b1), .CEALUMODE(1'b1), .CEB1(ce1), .CEB2(ce2), .CEC(1'b1), .CECARRYIN(1'b1), .CECTRL(1'b1), // opmode .CED(1'b1), .CEINMODE(1'b1), .CEM(cem), .CEP(cep), .RSTA(1'b0), .RSTALLCARRYIN(1'b0), .RSTALUMODE(1'b0), .RSTB(1'b0), .RSTC(1'b0), .RSTCTRL(1'b0), .RSTD(1'b0), .RSTINMODE(1'b0), .RSTM(1'b0), .RSTP(1'b0) ); endmodule // dsp48_wrap_f
Ex2:
/ /p = c + b * a 3 cycles if r else p = p + b * a
// p = c + b * a 3 cycles if r else p = p + b * a module macc ( input clock, input [2:0] ce, // bit 0 = a, 1 = b , 2 = c input r, // reset accumulator to c + a*b input signed [24:0] a, input signed [17:0] b, input signed [47:0] c, output signed [47-S:0] p; parameter S = 0; parameter AREG = 1; // 0 - 2 parameter BREG = 1; // 0 - 2 wire signed [47:0] dsp_p; assign p = dsp_p[47:S]; // X+Y is usually the multiplier output (M) // Z is either P, PCIN or C // bit 1:0: 0: Z+X+Y 3:Z-(X+Y) 1: -Z + (X+Y) 2: -1*(Z+X+Y+1) // bits 3:2, 0: Z=0, 1: Z=PCIN, 2: Z=P, 3: Z = C // bit 4: sub in pre add wire [4:0] mode = {1'b0, r ? 2'b11 : 2'b10, 2'b00}; DSP48E1 #( .A_INPUT("DIRECT"), // "DIRECT" "CASCADE" .B_INPUT("DIRECT"), // "DIRECT" "CASCADE" .USE_DPORT("FALSE"), .USE_MULT("MULTIPLY"),// "MULTIPLY" "DYNAMIC" "NONE" .USE_SIMD("ONE48"), // "ONE48" "TWO24" "FOUR12" // pattern detector - not used .AUTORESET_PATDET("NO_RESET"), .MASK(48'h3fffffffffff), .PATTERN(48'h000000000000), .SEL_MASK("MASK"), .SEL_PATTERN("PATTERN"), .USE_PATTERN_DETECT("NO_PATDET"), // register enables .ACASCREG(1), // pipeline stages between A/ACIN and ACOUT (0, 1 or 2) .ADREG(1), // pipeline stages for pre-adder (0 or 1) .ALUMODEREG(1), // pipeline stages for ALUMODE (0 or 1) .AREG(AREG), // pipeline stages for A (0, 1 or 2) .BCASCREG(1), // pipeline stages between B/BCIN and BCOUT (0, 1 or 2) .BREG(BREG), // pipeline stages for B (0, 1 or 2) .CARRYINREG(1), // this and below are 0 or 1 .CARRYINSELREG(1), .CREG(1), .DREG(1), .INMODEREG(1), .MREG(1), .OPMODEREG(1), .PREG(1)) dsp48_i ( // status .OVERFLOW(), .PATTERNDETECT(), .PATTERNBDETECT(), .UNDERFLOW(), // outs .CARRYOUT(), .P(dsp_p), // control .ALUMODE({2'd0, mode[1:0]}), .CARRYINSEL(3'd0), .CLK(clock), .INMODE({1'b0,mode[4],3'b100}), .OPMODE({1'b0,mode[3:2],4'b0101}), // signal inputs .A({5'd0,a}), // 30 .B(b), // 18 .C(c), // 48 .CARRYIN(1'b0), .D(25'd0), // 25 // cascade ports .ACOUT(), .BCOUT(), .CARRYCASCOUT(), .MULTSIGNOUT(), .PCOUT(), .ACIN(30'h0), .BCIN(18'h0), .CARRYCASCIN(1'b0), .MULTSIGNIN(1'b0), .PCIN(48'h0), // clock enables .CEA1(1'b1), .CEA2(ce[0]), .CEAD(1'b1), .CEALUMODE(1'b1), .CEB1(1'b1), .CEB2(ce[1]), .CEC(ce[2]), .CECARRYIN(1'b1), .CECTRL(1'b1), // opmode .CED(1'b1), .CEINMODE(1'b1), .CEM(1'b1), .CEP(1'b1), .RSTA(1'b0), .RSTALLCARRYIN(1'b0), .RSTALUMODE(1'b0), .RSTB(1'b0), .RSTC(1'b0), .RSTCTRL(1'b0), .RSTD(1'b0), .RSTINMODE(1'b0), .RSTM(1'b0), .RSTP(1'b0) ); endmodule
Ex3:(35bit * 25bit,级联)
// wide multiply using 2x DSP48E1
// p = ((a * b) + c), 4 clock pipe delay
`timescale 1ns / 1ps // wide multiply using 2x DSP48E1 // p = ((a * b) + c), 4 clock pipe delay module mult_35x25 ( input clock, input signed [24:0] a, input signed [34:0] b, input signed [47:0] c, output signed [64:0] p); wire signed [29:0] low_acout; wire signed [47:0] low_pcout; wire [47:0] p_low3; reg [16:0] p_low4; DSP48E1 #(.A_INPUT("CASCADE"), .AREG(1), .BREG(2)) dsp48_high ( // status .OVERFLOW(), .PATTERNDETECT(), .PATTERNBDETECT(), .UNDERFLOW(), // outs .P(p[64:17]), .CARRYOUT(), // control .ALUMODE(4'b0), .CARRYINSEL(3'd0), .CLK(clock), .INMODE(5'b00000), .OPMODE(7'b1010101), // a*b + pcin >> 17 // signal inputs .A(30'b0), .B(b[34:17]), .C(48'b0), .CARRYIN(1'b0), .D(25'b0), // cascade ports .ACOUT(), .BCOUT(), .CARRYCASCOUT(), .MULTSIGNOUT(), .PCOUT(), .ACIN(low_acout), .BCIN(18'h0), .CARRYCASCIN(1'b0), .MULTSIGNIN(1'b0), .PCIN(low_pcout), // clock enables, resets .CEA1(1'b1), .CEA2(1'b1), .CEAD(1'b1), .CEALUMODE(1'b1), .CEB1(1'b1), .CEB2(1'b1), .CEC(1'b1), .CECARRYIN(1'b1), .CECTRL(1'b1), .CED(1'b1), .CEINMODE(1'b1), .CEM(1'b1), .CEP(1'b1), .RSTA(1'b0), .RSTALLCARRYIN(1'b0), .RSTALUMODE(1'b0), .RSTB(1'b0), .RSTC(1'b0), .RSTCTRL(1'b0), .RSTD(1'b0), .RSTINMODE(1'b0), .RSTM(1'b0), .RSTP(1'b0) ); DSP48E1 #(.ACASCREG(1), .AREG(1), .BREG(1)) dsp48_low ( // status .OVERFLOW(), .PATTERNDETECT(), .PATTERNBDETECT(), .UNDERFLOW(), // outs .P(p_low3), .CARRYOUT(), // control .ALUMODE(4'b0), .CARRYINSEL(3'd0), .CLK(clock), .INMODE(5'b00000), .OPMODE(7'b0110101), // signal inputs .A({{5{a[24]}},a}), .B({1'b0,b[16:0]}), .C(c), .CARRYIN(1'b0), .D(25'b0), // cascade ports .ACOUT(low_acout), .BCOUT(), .CARRYCASCOUT(), .MULTSIGNOUT(), .PCOUT(low_pcout), .ACIN(30'h0), .BCIN(18'h0), .CARRYCASCIN(1'b0), .MULTSIGNIN(1'b0), .PCIN(48'h0), // clock enables, resets .CEA1(1'b1), .CEA2(1'b1), .CEAD(1'b1), .CEALUMODE(1'b1), .CEB1(1'b1), .CEB2(1'b1), .CEC(1'b1), .CECARRYIN(1'b1), .CECTRL(1'b1), .CED(1'b1), .CEINMODE(1'b1), .CEM(1'b1), .CEP(1'b1), .RSTA(1'b0), .RSTALLCARRYIN(1'b0), .RSTALUMODE(1'b0), .RSTB(1'b0), .RSTC(1'b0), .RSTCTRL(1'b0), .RSTD(1'b0), .RSTINMODE(1'b0), .RSTM(1'b0), .RSTP(1'b0) ); always @ (posedge clock) begin p_low4 <= p_low3[16:0]; end assign p[16:0] = p_low4; initial begin $dumpfile("dump.vcd"); $dumpvars(0); end endmodule