Я лично взял кусок, переработал его немного под себя, описал ограничения в ucf и пользуюсь уже полгода, правда в связке с ml605
Код
module DAC_ADC_fmc3(
// system signals //
input ADC_clk,
input rstADC,
// DAC signals //
output tx_clk_out_p,
output tx_clk_out_n,
output tx_frame_out_p,
output tx_frame_out_n,
output [5:0] tx_data_out_p,
output [5:0] tx_data_out_n,
// ADC signals //
input rx_clk_in_p,
input rx_clk_in_n,
input rx_frame_in_p,
input rx_frame_in_n,
input [5:0] rx_data_in_p,
input [5:0] rx_data_in_n,
// data signals //
input [11:0] dataI,
input [11:0] dataQ,
output signed [11:0] rec_dataI,
output signed [11:0] rec_dataQ,
output test_data
)/*synthesis syn_hier="hard"*/;
///////////////////////
// DAC module //
///////////////////////
reg [5:0] tx_data_p=6'd0;
reg [5:0] tx_data_n=6'd0;
reg tx_frame;
reg [11:0] I1_d;
reg [11:0] I2_d;
reg [11:0] Q1_d;
reg [11:0] Q2_d;
reg [11:0] I1,Q1,I2,Q2;
// mux dac formation //
reg [1:0] tx_data_cnt=2'd0;
always @(posedge ADC_clk or posedge rstADC)
if (rstADC) begin
I1<=0;
Q1<=0;
I2<=0;
Q2<=0;
end
else if (&tx_data_cnt) begin
I2<=dataI;
Q2<=dataQ;
I1<=0;
Q1<=0;
end
always @(posedge ADC_clk)
if (~tx_frame) begin
I1_d<=I1_d;
Q1_d<=Q1_d;
I2_d<=0;
Q2_d<=0;
end
else begin
I2_d<=0;
Q2_d<=0;
I1_d<=/*Q2*/Q2;
Q1_d<=/*I2*/I2;
end
always @(posedge ADC_clk) tx_data_cnt<=tx_data_cnt+2'd1;
always @(posedge ADC_clk) case (tx_data_cnt)
2'b00: begin
tx_data_p<=I1_d[11:6];
tx_data_n<=Q1_d[11:6];
tx_frame<=1'b1;
end
2'b001: begin
tx_data_p<=I1_d[5:0];
tx_data_n<=Q1_d[5:0];
tx_frame<=1'b1;
end
2'b010: begin
tx_data_p<=I2_d[11:6];
tx_data_n<=Q2_d[11:6];
tx_frame<=1'b0;
end
2'b011: begin
tx_data_p<=I2_d[5:0];
tx_data_n<=Q2_d[5:0];
tx_frame<=1'b0;
end
default:;
endcase
wire [5:0] tx_data_oddr_s;
genvar l_inst;
generate
for (l_inst = 0; l_inst <= 5; l_inst = l_inst + 1) begin: g_tx_data
ODDR #(
.DDR_CLK_EDGE ("SAME_EDGE"),
.INIT (1'b0),
.SRTYPE ("ASYNC"))
i_tx_data_oddr (
.CE (1'b1),
.R (1'b0),
.S (1'b0),
.C (ADC_clk),
.D1 (tx_data_p[l_inst]),
.D2 (tx_data_n[l_inst]),
.Q (tx_data_oddr_s[l_inst]));
OBUFDS i_tx_data_obuf (
.I (tx_data_oddr_s[l_inst]),
.O (tx_data_out_p[l_inst]),
.OB (tx_data_out_n[l_inst]));
end
endgenerate
ODDR #(
.DDR_CLK_EDGE ("SAME_EDGE"),
.INIT (1'b0),
.SRTYPE ("ASYNC"))
i_tx_frame_oddr (
.CE (1'b1),
.R (1'b0),
.S (1'b0),
.C (ADC_clk),
.D1 (tx_frame),
.D2 (tx_frame),
.Q (tx_frame_oddr_s));
OBUFDS i_tx_frame_obuf (
.I (tx_frame_oddr_s),
.O (tx_frame_out_p),
.OB (tx_frame_out_n));
ODDR #(
.DDR_CLK_EDGE ("SAME_EDGE"),
.INIT (1'b0),
.SRTYPE ("ASYNC"))
i_tx_clk_oddr (
.CE (1'b1),
.R (1'b0),
.S (1'b0),
.C (ADC_clk),
.D1 (1'b0),
.D2 (1'b1),
.Q (tx_clk_oddr_s));
OBUFDS i_tx_clk_obuf (
.I (tx_clk_oddr_s),
.O (tx_clk_out_p),
.OB (tx_clk_out_n));
///////////////////////
// ADC module //
///////////////////////
assign test_data=(|adc_data_i1)|(|adc_data_i2)|(|adc_data_q1)|(|adc_data_q2);
reg [11:0] adc_data_i1;
reg [11:0] adc_data_q1;
reg signed [11:0] adc_data_i2;
reg signed [11:0] adc_data_q2;
wire rx_frame_ibuf_s;
wire rx_frame_p_s,rx_frame_n_s;
reg rx_frame_n;
reg [1:0] rx_frame;
reg [1:0] rx_frame_d;
wire [3:0] rx_frame_s;
wire [5:0] rx_data_ibuf_s;
wire [5:0] rx_data_p_s,rx_data_n_s;
reg [5:0] rx_data_n;
reg [11:0] rx_data_d;
reg [11:0] rx_data;
reg [11:0] rx_data_i1_r2;
reg [11:0] rx_data_q1_r2;
reg [11:0] rx_data_i2_r2;
reg [11:0] rx_data_q2_r2;
always @(posedge ADC_clk) begin
rx_data_n <= rx_data_n_s;
rx_frame_n <= rx_frame_n_s;
rx_data <= {rx_data_n, rx_data_p_s};
rx_frame <= {rx_frame_n, rx_frame_p_s};
rx_data_d <= rx_data;
rx_frame_d <= rx_frame;
end
assign rx_frame_s = {rx_frame_d, rx_frame};
always @(posedge ADC_clk) begin
if (rx_frame_s == 4'b1111) begin
rx_data_i1_r2 <= {rx_data_d[11:6], rx_data[11:6]};
rx_data_q1_r2 <= {rx_data_d[ 5:0], rx_data[ 5:0]};
end
else;
if (rx_frame_s == 4'b0000) begin
rx_data_i2_r2 <= {rx_data_d[11:6], rx_data[11:6]};
rx_data_q2_r2 <= {rx_data_d[ 5:0], rx_data[ 5:0]};
end
else;
end
always @(posedge ADC_clk)
begin
adc_data_i2 <= rx_data_i1_r2;
adc_data_q2 <= rx_data_q1_r2;
adc_data_i1 <= rx_data_i2_r2;
adc_data_q1 <= rx_data_q2_r2;
end
IBUFDS i_rx_frame_ibuf (
.I (rx_frame_in_p),
.IB (rx_frame_in_n),
.O (rx_frame_ibuf_s));
IDDR #(
.DDR_CLK_EDGE ("SAME_EDGE_PIPELINED"),
.INIT_Q1 (1'b0),
.INIT_Q2 (1'b0),
.SRTYPE ("ASYNC"))
i_rx_frame_iddr (
.CE (1'b1),
.R (1'b0),
.S (1'b0),
.C (ADC_clk),
.D (rx_frame_ibuf_s),
.Q1 (rx_frame_p_s),
.Q2 (rx_frame_n_s));
generate
for (l_inst = 0; l_inst <= 5; l_inst = l_inst + 1) begin: g_rx_data
IBUFDS i_rx_data_ibuf (
.I (rx_data_in_p[l_inst]),
.IB (rx_data_in_n[l_inst]),
.O (rx_data_ibuf_s[l_inst]));
IDDR #(
.DDR_CLK_EDGE ("SAME_EDGE_PIPELINED"),
.INIT_Q1 (1'b0),
.INIT_Q2 (1'b0),
.SRTYPE ("ASYNC"))
i_rx_data_iddr (
.CE (1'b1),
.R (1'b0),
.S (1'b0),
.C (ADC_clk),
.D (rx_data_ibuf_s[l_inst]),
.Q1 (rx_data_p_s[l_inst]),
.Q2 (rx_data_n_s[l_inst]));
end
endgenerate
reg [1:0] cnt_clk=0;
assign rec_dataI=adc_data_i1;
assign rec_dataQ=adc_data_q1;
endmodule