aboutsummaryrefslogtreecommitdiff
path: root/rtl/modexpng_recombinator_cell.v
diff options
context:
space:
mode:
Diffstat (limited to 'rtl/modexpng_recombinator_cell.v')
-rw-r--r--rtl/modexpng_recombinator_cell.v188
1 files changed, 148 insertions, 40 deletions
diff --git a/rtl/modexpng_recombinator_cell.v b/rtl/modexpng_recombinator_cell.v
index 45fc68c..0c9ab00 100644
--- a/rtl/modexpng_recombinator_cell.v
+++ b/rtl/modexpng_recombinator_cell.v
@@ -34,7 +34,7 @@ module modexpng_recombinator_cell
(
clk,
ce, clr,
- din, dout, dout_ext
+ din, dout, doutw
);
@@ -54,63 +54,172 @@ module modexpng_recombinator_cell
input clr;
input [ MAC_W -1:0] din;
output [WORD_W -1:0] dout;
- output [WORD_W :0] dout_ext;
+ output [WORD_W :0] doutw;
//
// din <=> {z[13:0], y[15:0], x[15:0]}
//
- wire [WORD_W -3:0] din_z = din[3 * WORD_W -3 : 2 * WORD_W]; // [45:32]
- wire [WORD_W -1:0] din_y = din[2 * WORD_W -1 : WORD_W]; // [31:16]
- wire [WORD_W -1:0] din_x = din[ WORD_W -1 : 0]; // [15: 0]
-
+ wire [WORD_W -1:0] din_z = {2'b00, din[3 * WORD_W -3 : 2 * WORD_W]}; // [47:46][45:32]
+ wire [WORD_W -1:0] din_y = { din[2 * WORD_W -1 : WORD_W]}; // [31:16]
+ wire [WORD_W -1:0] din_x = { din[ WORD_W -1 : 0]}; // [15: 0]
+
//
- // Delayed Clock Enable
+ // Delayed Clock Enables
+ //
+ reg ce_dly1 = 1'b0, ce_dly2 = 1'b0, ce_dly3 = 1'b0, ce_dly4 = 1'b0, ce_dly5 = 1'b0, ce_dly6 = 1'b0;
+ always @(posedge clk) {ce_dly1, ce_dly2, ce_dly3, ce_dly4, ce_dly5, ce_dly6} <= {ce, ce_dly1, ce_dly2, ce_dly3, ce_dly4, ce_dly5};
+
+
+ //
+ // Delayed Clear
//
- reg ce_dly = 1'b0;
- always @(posedge clk) ce_dly <= ce;
+ reg clr_dly1, clr_dly2, clr_dly3, clr_dly4;
+ always @(posedge clk) {clr_dly1, clr_dly2, clr_dly3, clr_dly4} <= {clr, clr_dly1, clr_dly2, clr_dly3};
+
+ //
+ // Phase Flip-Flop
+ //
+ reg phase_ff, phase_ff_dly1, phase_ff_dly2, phase_ff_dly3, phase_ff_dly4, phase_ff_dly5;
+ always @(posedge clk)
+ if (ce) phase_ff <= ~phase_ff;
+ else if (clr) phase_ff <= 1'b0;
+
+ always @(posedge clk)
+ {phase_ff_dly1, phase_ff_dly2, phase_ff_dly3, phase_ff_dly4, phase_ff_dly5} <= {phase_ff, phase_ff_dly1, phase_ff_dly2, phase_ff_dly3, phase_ff_dly4};
+
//
- // DSP Slice Buses
+ // Shift Registers
//
- wire [DSP48E1_A_W-1:0] a_int;
- wire [DSP48E1_B_W-1:0] b_int;
- wire [DSP48E1_C_W-1:0] c_int;
- wire [DSP48E1_P_W-1:0] p_int;
+ reg [WORD_W-1:0] din_x_dly1;
+ reg [WORD_W-1:0] din_y_dly1;
+ reg [WORD_W-1:0] din_z_dly1;
+ reg [WORD_W-1:0] din_z_dly2;
- assign {a_int, b_int} = {{(DSP48E1_C_W-(2*WORD_W+1)){1'b0}}, din_z, din_y[WORD_W-1], din_y};
- assign {c_int} = {{(DSP48E1_C_W-(2*WORD_W+1)){1'b0}}, WORD_ZERO, din_x[WORD_W-1], din_x};
+ always @(posedge clk) begin
+ //
+ if (ce) {din_x_dly1, din_y_dly1, din_z_dly1} <= {din_x, din_y, din_z};
+ else if (clr) {din_x_dly1, din_y_dly1, din_z_dly1} <= {WORD_ZERO, WORD_ZERO, WORD_ZERO};
+ //
+ if (ce) {din_z_dly2} <= {din_z_dly1};
+ else if (clr) {din_z_dly2} <= {WORD_ZERO};
+ //
+ end
+
+ //
+ // DSP Input Registers
//
- // Combinational OPMODE Switch
+ reg [2 * WORD_W-1:0] master_ab_reg;
+ reg [2 * WORD_W-1:0] master_c_reg;
+
+ reg [ WORD_W+1:0] slave_ab_reg;
+ reg [ WORD_W+1:0] slave_ab_next_reg;
+
+
+ //
+ // DSP Cascade Bus
+ //
+ wire [DSP48E1_P_W-1:0] master_slave_p_int;
+
+
+ //
+ // DSP Output Buses
//
- reg [DSP48E1_OPMODE_W-1:0] opmode;
+ wire [DSP48E1_P_W-1:0] master_p_int;
+ wire [DSP48E1_P_W-1:0] slave_p_int;
+
- always @(clr)
- //
- case (clr)
- 1'b1: opmode = DSP48E1_OPMODE_Z0_YC_X0;
- 1'b0: opmode = DSP48E1_OPMODE_ZP17_YC_XAB;
- endcase
+ //
+ // DSP Input Mapping
+ //
+ wire [DSP48E1_C_W-1:0] master_ab_int = {{(DSP48E1_C_W - 2 * WORD_W){1'b0}}, master_ab_reg};
+ wire [DSP48E1_C_W-1:0] master_c_int = {{(DSP48E1_C_W - 2 * WORD_W){1'b0}}, master_c_reg};
+
+ wire [DSP48E1_C_W-1:0] slave_ab_int = {{(DSP48E1_C_W - (WORD_W+3)){1'b0}}, slave_ab_reg[WORD_W+1:WORD_W], 1'b1, slave_ab_reg[WORD_W-1:0]};
+ wire [DSP48E1_C_W-1:0] slave_c_int = {DSP48E1_C_W{1'b0}};
//
- // DSP Slice Instance
+ // Master DSP Input Logic
//
- `MODEXPNG_DSP_SLICE_ADDSUB #(.AB_REG(2)) dsp_inst
+ always @(posedge clk)
+ //
+ if (ce) begin
+ master_ab_reg <= !phase_ff ? {din_y, din_y_dly1} : {din_x, din_x_dly1};
+ master_c_reg <= !phase_ff ? {din_z_dly1, din_z_dly2} : {WORD_DNC, WORD_DNC};
+ end else begin
+ master_ab_reg <= {WORD_DNC, WORD_DNC};
+ master_c_reg <= {WORD_DNC, WORD_DNC};
+ end
+
+
+ //
+ // Slave DSP Input Logic
+ //
+ always @(posedge clk) begin
+ //
+ slave_ab_reg <= {(WORD_W+2){1'bX}};
+ slave_ab_next_reg <= {(WORD_W+2){1'bX}};
+ //
+ if (ce_dly3 && phase_ff_dly3) slave_ab_next_reg <= {master_p_int[2*WORD_W+1:WORD_W]};
+ //
+ if (ce_dly3 && phase_ff_dly3) slave_ab_reg <= {2'b00, master_p_int[WORD_W-1:0]};
+ if (ce_dly4 && phase_ff_dly4) slave_ab_reg <= slave_ab_next_reg;
+ //
+ end
+
+
+ //
+ // OPMODE Logic
+ //
+ reg [DSP48E1_OPMODE_W-1:0] master_opmode;
+ reg [DSP48E1_OPMODE_W-1:0] slave_opmode;
+
+ always @(posedge clk) begin
+ //
+ if (ce) master_opmode <= !phase_ff ? DSP48E1_OPMODE_Z0_YC_XAB : DSP48E1_OPMODE_ZP_Y0_XAB;
+ else master_opmode <= DSP48E1_OPMODE_DNC;
+ //
+ if (ce_dly4) slave_opmode <= clr_dly4 ? DSP48E1_OPMODE_Z0_Y0_XAB : DSP48E1_OPMODE_ZP17_Y0_XAB;
+ else slave_opmode <= DSP48E1_OPMODE_DNC;
+ //
+ end
+
+
+ //
+ // DSP Slice Instances
+ //
+ `MODEXPNG_DSP_SLICE_ADDSUB dsp_master_inst
+ (
+ .clk (clk),
+ .ce_abc (ce_dly1),
+ .ce_p (ce_dly2),
+ .ce_ctrl (ce_dly1),
+ .ab (master_ab_int),
+ .c (master_c_int),
+ .p (master_p_int),
+ .op_mode (master_opmode),
+ .alu_mode (DSP48E1_ALUMODE_Z_PLUS_X_AND_Y_AND_CIN),
+ .carry_in_sel (DSP48E1_CARRYINSEL_CARRYIN),
+ .casc_p_in (),
+ .casc_p_out (),
+ .carry_out ()
+ );
+
+ `MODEXPNG_DSP_SLICE_ADDSUB dsp_slave_inst
(
.clk (clk),
- .ce_ab1 (ce),
- .ce_ab2 (ce_dly),
- .ce_c (ce),
- .ce_p (ce_dly),
- .ce_ctrl (ce),
- .ab ({a_int, b_int}),
- .c (c_int),
- .p (p_int),
- .op_mode (opmode),
+ .ce_abc (ce_dly5),
+ .ce_p (ce_dly6),
+ .ce_ctrl (ce_dly5),
+ .ab (slave_ab_int),
+ .c (slave_c_int),
+ .p (slave_p_int),
+ .op_mode (slave_opmode),
.alu_mode (DSP48E1_ALUMODE_Z_PLUS_X_AND_Y_AND_CIN),
.carry_in_sel (DSP48E1_CARRYINSEL_CARRYIN),
.casc_p_in (),
@@ -120,10 +229,9 @@ module modexpng_recombinator_cell
//
- // Output Mapping
- //
- assign dout = {p_int[WORD_W-1:0]};
- assign dout_ext = {p_int[WORD_W+1], dout};
-
+ // Output Register
+ //
+ assign dout = {slave_p_int[WORD_W-1:0]};
+ assign doutw = {slave_p_int[WORD_W+1], dout};
endmodule