fpga: Multiple X300 FPGA bugfixes and enhancements
- Fixed 10GigE firmware communication issues and sequence errors for TX - Multiple changes to help ease timing closure - Cleaned up build scripts - Switched to Xilinx ISE 14.7 as the default build tool for X300 Original-commit: 64d71dcbc5fa6790385b288de25224d386b047b0
This commit is contained in:
+75
-50
@@ -1,7 +1,6 @@
|
||||
|
||||
|
||||
module gen_ddrlvds
|
||||
(
|
||||
module gen_ddrlvds (
|
||||
// 2X Radio clock
|
||||
input tx_clk_2x,
|
||||
// 1X Radio Clock
|
||||
@@ -23,76 +22,102 @@ module gen_ddrlvds
|
||||
input [15:0] q,
|
||||
// Rising edge sampled on sync_dacs triggers frame sync sequence
|
||||
input sync_dacs
|
||||
);
|
||||
);
|
||||
|
||||
reg [15:0] i_reg, q_reg;
|
||||
reg [15:0] i_2x, q_2x;
|
||||
reg phase, phase_2x;
|
||||
reg rising_edge;
|
||||
wire [15:0] i_and_q_2x;
|
||||
reg sync_2x;
|
||||
reg sync_dacs_reg;
|
||||
|
||||
|
||||
|
||||
genvar z;
|
||||
wire [7:0] tx_int;
|
||||
wire tx_clk_2x_int;
|
||||
wire tx_frame_int;
|
||||
|
||||
(* keep = "true", max_fanout = 10 *) wire phase_eq_phase2x = (phase == phase_2x);
|
||||
localparam SYNC_PULSE_WIDTH = 3'd2;
|
||||
|
||||
//
|
||||
// Figure out the 1X clock level
|
||||
//
|
||||
localparam TX_CLK_1X_LOW = 1'b0;
|
||||
localparam TX_CLK_1X_HIGH = 1'b1;
|
||||
|
||||
reg tx_clk_1x_level;
|
||||
reg phase, phase_2x;
|
||||
reg reset_2x;
|
||||
|
||||
always @(posedge tx_clk_1x)
|
||||
if (reset)
|
||||
phase <= 1'b0;
|
||||
else
|
||||
phase <= ~phase;
|
||||
if (reset)
|
||||
phase <= 1'b0;
|
||||
else
|
||||
phase <= ~phase;
|
||||
|
||||
always @(posedge tx_clk_2x)
|
||||
begin
|
||||
phase_2x <= phase;
|
||||
//Pipeline reset and tx_clk_1x_level
|
||||
reset_2x <= reset;
|
||||
tx_clk_1x_level <= (phase == phase_2x) ? TX_CLK_1X_HIGH : TX_CLK_1X_LOW;
|
||||
end
|
||||
|
||||
//
|
||||
// Pipeline input data so that 1x to 2x clock domain jump includes no logic external to this module.
|
||||
//
|
||||
reg [15:0] i_reg, q_reg;
|
||||
reg sync_dacs_reg;
|
||||
|
||||
always @(posedge tx_clk_1x)
|
||||
begin
|
||||
i_reg <= i;
|
||||
q_reg <= q;
|
||||
sync_dacs_reg <= sync_dacs;
|
||||
end
|
||||
begin
|
||||
i_reg <= i;
|
||||
q_reg <= q;
|
||||
sync_dacs_reg <= sync_dacs;
|
||||
end
|
||||
|
||||
//
|
||||
// Generate frame signal and interleave I and Q signals
|
||||
//
|
||||
reg [15:0] i_2x, q_2x;
|
||||
reg [2:0] sync_count;
|
||||
reg frame;
|
||||
|
||||
always @(posedge tx_clk_2x)
|
||||
begin
|
||||
// Move 1x data to 2x domain, mostly just to add pipeline regs
|
||||
// for timing closure.
|
||||
i_2x <= i_reg;
|
||||
q_2x <= q_reg;
|
||||
// Sample phase to determine when 1x clock edges occur.
|
||||
// To sync multiple AD9146 DAC's an extended assertion of FRAME is required,
|
||||
// when sync flag set, squash one rising_edge assertion which causes a 3 word assertion of FRAME,
|
||||
// also reset sync flag. "sync_dacs" comes from 1x clk and pulse lasts 2 2x clock cycles...this is accounted for.
|
||||
sync_2x <= (phase_eq_phase2x && sync_2x) ? 1'b0 /*RESET */ : (sync_dacs_reg) ? 1'b1 /* SET */ : sync_2x /* HOLD */;
|
||||
rising_edge <= (phase_eq_phase2x && ~sync_2x);
|
||||
phase_2x <= phase;
|
||||
end
|
||||
begin
|
||||
// Move 1x data to 2x domain, mostly just to add pipeline regs
|
||||
// for timing closure.
|
||||
i_2x <= i_reg;
|
||||
q_2x <= q_reg;
|
||||
|
||||
// Sample phase to determine when 1x clock edges occur.
|
||||
// To sync multiple AD9146 DAC's an extended assertion of FRAME is required,
|
||||
// when sync flag set, squash one frame assertion which causes a SYNC_PULSE_WIDTH+1 word assertion of FRAME,
|
||||
// also reset sync flag. "sync_dacs" comes from 1x clk and pulse lasts 2 2x clock cycles...this is accounted for.
|
||||
if (reset_2x) begin
|
||||
frame <= 0;
|
||||
sync_count <= 3'd0;
|
||||
end else begin
|
||||
frame <= (tx_clk_1x_level == TX_CLK_1X_LOW) | (sync_count != 3'd0);
|
||||
if ((tx_clk_1x_level == TX_CLK_1X_LOW) & sync_dacs_reg)
|
||||
sync_count <= SYNC_PULSE_WIDTH;
|
||||
else if (sync_count > 3'd0)
|
||||
sync_count <= sync_count - 3'd1;
|
||||
end
|
||||
end
|
||||
|
||||
// Interleave I and Q as SDR signals
|
||||
assign i_and_q_2x = rising_edge ? q_2x : i_2x;
|
||||
wire [15:0] i_and_q_2x = frame ? i_2x : q_2x;
|
||||
|
||||
//
|
||||
// Instantiate IO primitives for the source synchronous interface
|
||||
//
|
||||
wire [7:0] tx_int;
|
||||
wire tx_clk_2x_int;
|
||||
wire tx_frame_int;
|
||||
|
||||
genvar z;
|
||||
generate
|
||||
for(z = 0; z < 8; z = z + 1)
|
||||
begin : gen_pins
|
||||
OBUFDS obufds (.I(tx_int[z]), .O(tx_d_p[z]), .OB(tx_d_n[z]));
|
||||
ODDR #(.DDR_CLK_EDGE("SAME_EDGE")) oddr
|
||||
(.Q(tx_int[z]), .C(tx_clk_2x),
|
||||
.CE(1'b1), .D1(i_and_q_2x[z+8]), .D2(i_and_q_2x[z]), .S(1'b0), .R(1'b0));
|
||||
end
|
||||
begin : gen_pins
|
||||
OBUFDS obufds (.I(tx_int[z]), .O(tx_d_p[z]), .OB(tx_d_n[z]));
|
||||
ODDR #(.DDR_CLK_EDGE("SAME_EDGE")) oddr
|
||||
(.Q(tx_int[z]), .C(tx_clk_2x),
|
||||
.CE(1'b1), .D1(i_and_q_2x[z+8]), .D2(i_and_q_2x[z]), .S(1'b0), .R(1'b0));
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Generate framing signal to identify I and Q
|
||||
OBUFDS obufds_frame (.I(tx_frame_int), .O(tx_frame_p), .OB(tx_frame_n));
|
||||
ODDR #(.DDR_CLK_EDGE("SAME_EDGE")) oddr_frame
|
||||
(.Q(tx_frame_int), .C(tx_clk_2x),
|
||||
.CE(1'b1), .D1(~rising_edge), .D2(~rising_edge), .S(1'b0), .R(1'b0));
|
||||
.CE(1'b1), .D1(frame), .D2(frame), .S(1'b0), .R(1'b0));
|
||||
|
||||
// Source synchronous clk
|
||||
OBUFDS obufds_clk (.I(tx_clk_2x_int), .O(tx_clk_2x_p), .OB(tx_clk_2x_n));
|
||||
|
||||
Reference in New Issue
Block a user