|
|
  |
трансивер ad_9361 + Zynq (Интерфейс LVDS) |
|
|
|
Feb 1 2015, 13:31
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 6-03-14
Из: Зеленоград
Пользователь №: 80 823

|
Здравствуйте, подскажите кто работал с данной микросхемой. Необходимо связать данную микросхему трансивера с плис, в качестве интерфейса используется lvds, и на плис необходимо описать блок преобразования принимаемых данных. Analog devices приводит пример дизайна данного блока, описанный в axi_ad9361_dev_if.v но там есть сигналы // delay control signals. Вопрос как с ними работать и и правильны ли мои рассуждения по описанию блока для приема lvds сигналов от трансивера?
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;
// physical interface (transmit)
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;
// clock (common to both receive and transmit)
output clk;
// receive data path interface
output adc_valid; output [11:0] adc_data_i1; output [11:0] adc_data_q1; output [11:0] adc_data_i2; output [11:0] adc_data_q2; output adc_status; input adc_r1_mode;
// transmit data path interface
input dac_valid; input [11:0] dac_data_i1; input [11:0] dac_data_q1; input [11:0] dac_data_i2; input [11:0] dac_data_q2; input dac_r1_mode;
// delay control signals
input delay_clk; input delay_rst; input delay_sel; input delay_rwn; input [ 7:0] delay_addr; input [ 4:0] delay_wdata; output [ 4:0] delay_rdata; output delay_ack_t; output delay_locked;
|
|
|
|
|
Feb 2 2015, 08:31
|
Знающий
   
Группа: Участник
Сообщений: 835
Регистрация: 9-08-08
Из: Санкт-Петербург
Пользователь №: 39 515

|
Цитата(Alexey_pashinov @ Feb 1 2015, 16:31)  Здравствуйте, подскажите кто работал с данной микросхемой. Необходимо связать данную микросхему трансивера с плис, в качестве интерфейса используется lvds, и на плис необходимо описать блок преобразования принимаемых данных. Analog devices приводит пример дизайна данного блока, описанный в axi_ad9361_dev_if.v но там есть сигналы // delay control signals. Вопрос как с ними работать и и правильны ли мои рассуждения по описанию блока для приема lvds сигналов от трансивера? А какие у вас рассуждения? Пример от AD плохой, в качестве основы лучше взять xapp860. В вашем случае, думаю, придётся мониторить окно только для rx_frame, и по нему синхронно подстраивать задержки всех данных. Кроме того, можно подстраивать задержку и для входного клока, что позволит раширить диапазон подстройки. Это всё, если частота не ниже 150-200МГц DDR, иначе придётся поворачивать фазу на MMCM.
|
|
|
|
|
Feb 2 2015, 11:02
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 6-03-14
Из: Зеленоград
Пользователь №: 80 823

|
В том примере, который они приводитят (axi_ad9361_dev_if.v) реализовано выделение из данных rx_data_in_p(n) мнимой и действительной частей сигнала, выходящих с ацп. (в Вашем примере придется писать все самому, да и зачем, если AD приводит примеры)). Вопрос же что делать с сигналами delay control, как с ними работать применительно к данной микросхеме?
|
|
|
|
|
Feb 2 2015, 11:44
|
Знающий
   
Группа: Участник
Сообщений: 835
Регистрация: 9-08-08
Из: Санкт-Петербург
Пользователь №: 39 515

|
Цитата(Alexey_pashinov @ Feb 2 2015, 14:02)  В том примере, который они приводитят (axi_ad9361_dev_if.v) реализовано выделение из данных rx_data_in_p(n) мнимой и действительной частей сигнала, выходящих с ацп. (в Вашем примере придется писать все самому, да и зачем, если AD приводит примеры)). Вопрос же что делать с сигналами delay control, как с ними работать применительно к данной микросхеме? axi_ad9361_dev_if.v написан по принципу "на отвяжись", правильно сделать выравнивание клока на его основе невозможно. Хотя можно подогнать эти самые delay, чтобы оно как-то работало на определённом чипе при определённой температуре и напряжении. Или даже не подгонять, скорее всего и так заработает, это стандартная китайская технология  . А по-хорошему - это xapp860.
|
|
|
|
|
Feb 2 2015, 12:00
|
Профессионал
    
Группа: Свой
Сообщений: 1 088
Регистрация: 20-10-09
Из: Химки
Пользователь №: 53 082

|
Я лично взял кусок, переработал его немного под себя, описал ограничения в 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
|
|
|
|
|
Feb 2 2015, 12:46
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 6-03-14
Из: Зеленоград
Пользователь №: 80 823

|
Спасибо за советы  Попробую все таки пока поработать с axi_ad9361_dev_if.v и проверить его работу, а дальше по обстоятельствам.
|
|
|
|
|
Feb 5 2015, 15:10
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 6-03-14
Из: Зеленоград
Пользователь №: 80 823

|
Решил последовать примеру bogaev_roman'a и переработать предложенный экземпл. Убрал все элементы задержки и переписал с неудобного мне верилога на vhdl. Вопрос сначала про передачу. В прикрепленном файле показана диаграмма передачи последовательно двух наборов данных. Для передачи каждого набора данных выставляется свой valid, получается при начале второй транзакции сначала выставляется valid и в это время передаются нулевые данные, а после только идут данные на передачу, эта ситуация на рис отмечена красным. В UG приводят диаграмму где данные идут друг за другом и там нет промежуточных нулевых данных, как получить похожую диаграмму? Было бы здорово, если кто поделился времянками)
Сообщение отредактировал Alexey_pashinov - Feb 5 2015, 15:12
Эскизы прикрепленных изображений
|
|
|
|
|
Feb 6 2015, 09:45
|
Профессионал
    
Группа: Свой
Сообщений: 1 088
Регистрация: 20-10-09
Из: Химки
Пользователь №: 53 082

|
Не очень понятен Ваш вопрос. В данном режиме приемопередачи используются два канала. Формируете счетчик от 0 до 3 и с помощью него получаете данные и фрейм, которые пускаете дальше, считается что частота входных данных, предназначенных для передачи в 4 раза меньше dac_clk: always @(posedge ADC_clk) tx_data_cnt<=tx_data_cnt+2'd1; Код 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) 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 Т. е. в данном случае формируется независимый счетчик от 0 до 3, при значении 3 входные данные записываются в промежуточный регистр и дальше согласно временной диаграмме, указанной в документации формируются сигналы: при 0 - формируется старшая часть первого канала (frame=1), при 1 - формируется младшая часть первого канала (frame=1), при 2 - формируется старшая часть второго канала (frame=0), при 3 - формируется младшая часть второго канала (frame=0).
|
|
|
|
|
Feb 6 2015, 10:04
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 6-03-14
Из: Зеленоград
Пользователь №: 80 823

|
Повнимательней просмотрел ваш код и увидел что вы не используете сигнал начала передачи valid, который был в примере. Я его использовал, поэтому перед тем как попасть в автомат, формирующий данные и сигнал фрейм, нужно дождаться условия valid = '1'. Собственно из за этого и были задержки в один такт между двумя похождениями автомата. В общем уберу этот сигнал) спасибо за ваш ответ и еще был вопрос по rx, если тогда не решу проблему выложу времянки в понедельник)
|
|
|
|
|
Feb 10 2015, 06:58
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 6-03-14
Из: Зеленоград
Пользователь №: 80 823

|
Закончил описание этого интерфейса. Т.к. мой трансивер имеет по 2 отдельных канала на прием и передачу, в описанном модуле с помощью сигнала xxx_r1_mode можно выбрать режим (одноканальный - '1' или двуканальный - '0') В итоге получилось данное творение CODE library unisim; use unisim.vcomponents.all;
library IEEE; use IEEE.STD_LOGIC_1164.ALL; USE ieee.numeric_std.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all;
entity ad9361_lvds is port( -- physical interface (receive) rx_clk_in_p : in std_logic; rx_clk_in_n : in std_logic; rx_frame_in_p : in std_logic; rx_frame_in_n : in std_logic; rx_data_in_p : in std_logic_vector(5 downto 0); rx_data_in_n : in std_logic_vector(5 downto 0);
-- physical interface (transmit) tx_clk_out_p : out std_logic; tx_clk_out_n : out std_logic; tx_frame_out_p : out std_logic; tx_frame_out_n : out std_logic; tx_data_out_p : out std_logic_vector(5 downto 0); tx_data_out_n : out std_logic_vector(5 downto 0); -- receive data path interface adc_data_i1 : out std_logic_vector(11 downto 0); adc_data_q1 : out std_logic_vector(11 downto 0); adc_data_i2 : out std_logic_vector(11 downto 0); adc_data_q2 : out std_logic_vector(11 downto 0); adc_status : out std_logic; adc_r1_mode : in std_logic;
-- transmit data path interface dac_valid : in std_logic; dac_data_i1 : in std_logic_vector(11 downto 0); dac_data_q1 : in std_logic_vector(11 downto 0); dac_data_i2 : in std_logic_vector(11 downto 0); dac_data_q2 : in std_logic_vector(11 downto 0); dac_r1_mode : in std_logic ); end ad9361_lvds;
architecture Behavioral of ad9361_lvds is signal clk : std_logic; signal clk_ibuf_s : std_logic; signal rx_frame_ibuf_s : std_logic; signal rx_frame_p_s : std_logic; signal rx_frame_n_s : std_logic; signal rx_data_ibuf_s : std_logic_vector(5 downto 0); signal rx_data_p_s : std_logic_vector(5 downto 0); signal rx_data_n_s : std_logic_vector(5 downto 0); signal rx_frame_s : std_logic_vector(3 downto 0) := "0000"; signal rx_frame : std_logic_vector(1 downto 0) := "00"; signal rx_frame_d : std_logic_vector(1 downto 0) := "00"; signal rx_frame_n : std_logic := '0'; signal rx_data_n : std_logic_vector(5 downto 0) := "000000"; signal rx_data : std_logic_vector(11 downto 0) := x"000"; signal rx_data_d : std_logic_vector(11 downto 0) := x"000"; signal rx_data_i_r1 : std_logic_vector(11 downto 0) := x"000"; signal rx_data_q_r1 : std_logic_vector(11 downto 0) := x"000"; signal rx_data_i1_r2 : std_logic_vector(11 downto 0) := x"000"; signal rx_data_q1_r2 : std_logic_vector(11 downto 0) := x"000"; signal rx_data_i2_r2 : std_logic_vector(11 downto 0) := x"000"; signal rx_data_q2_r2 : std_logic_vector(11 downto 0) := x"000"; signal tx_clk_oddr_s : std_logic; signal tx_data_sel_s : std_logic_vector(3 downto 0); signal tx_data_cnt : std_logic_vector(2 downto 0) := "000"; signal tx_data_i1_d : std_logic_vector(11 downto 0) := x"000"; signal tx_data_q1_d : std_logic_vector(11 downto 0) := x"000"; signal tx_data_i2_d : std_logic_vector(11 downto 0) := x"000"; signal tx_data_q2_d : std_logic_vector(11 downto 0) := x"000"; signal tx_data_p : std_logic_vector(5 downto 0) := "000000"; signal tx_data_n : std_logic_vector(5 downto 0) := "000000"; signal tx_frame : std_logic := '0';
signal tx_frame_oddr_s : std_logic; signal tx_data_oddr_s : std_logic_vector(5 downto 0); signal count : std_logic_vector(2 downto 0) := "000"; begin ---------- RX_frame/data ---------- ----------------------------------- rx_frame_s <= rx_frame_d & rx_frame; count_process : process(clk) begin if (rising_edge(clk)) then if (rx_frame_p_s = '0') then count <= count + 1; else count <= "000"; end if; end if; end process;
rx_frame_process : process(clk) begin if (rising_edge(clk)) then 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 if; end process; one_channel : process(clk) begin if (rising_edge(clk)) then if (rx_frame_s = "1100") then rx_data_i_r1 <= rx_data_d(11 downto 6) & rx_data(11 downto 6); rx_data_q_r1 <= rx_data_d(5 downto 0) & rx_data(5 downto 0); end if; end if; end process; two_channel : process(clk) begin if (rising_edge(clk)) then if (rx_frame_s = "1111") then rx_data_i1_r2 <= rx_data_d(11 downto 6) & rx_data(11 downto 6); rx_data_q1_r2 <= rx_data_d(5 downto 0) & rx_data(5 downto 0); elsif (rx_frame_s = "0000") then if (count > 2) then rx_data_i2_r2 <= "000000000000"; rx_data_q2_r2 <= "000000000000"; else rx_data_i2_r2 <= rx_data_d(11 downto 6) & rx_data(11 downto 6); rx_data_q2_r2 <= rx_data_d(5 downto 0) & rx_data(5 downto 0); end if; end if; end if; end process; rx_data_process : process(clk) begin if (rising_edge(clk)) then if (adc_r1_mode = '1') then adc_data_i1 <= rx_data_i_r1; adc_data_q1 <= rx_data_q_r1; adc_data_i2 <= x"000"; adc_data_q2 <= x"000"; else adc_data_i1 <= rx_data_i1_r2; adc_data_q1 <= rx_data_q1_r2; adc_data_i2 <= rx_data_i2_r2; adc_data_q2 <= rx_data_q2_r2; end if; end if; end process; ---------- TX_frame/data ---------- ----------------------------------- tx_data_sel_s <= (tx_data_cnt(2) & dac_r1_mode & tx_data_cnt(1 downto 0)); tx_data_process : process(clk) begin if (rising_edge(clk)) then tx_data_i1_d <= dac_data_i1; tx_data_q1_d <= dac_data_q1; tx_data_i2_d <= dac_data_i2; tx_data_q2_d <= dac_data_q2; end if; end process; tx_process : process(clk) begin if (rising_edge(clk)) then if (dac_valid = '1') then case (tx_data_sel_s) is when "1111" => tx_frame <= '0'; tx_data_p <= tx_data_i1_d(5 downto 0); tx_data_n <= tx_data_q1_d(5 downto 0); tx_data_cnt <= "100";
when "1110" => tx_frame <= '1'; tx_data_p <= tx_data_i1_d(11 downto 6); tx_data_n <= tx_data_q1_d(11 downto 6); tx_data_cnt <= tx_data_cnt + 1; when "1101" => tx_frame <= '0'; tx_data_p <= tx_data_i1_d(5 downto 0); tx_data_n <= tx_data_q1_d(5 downto 0); tx_data_cnt <= tx_data_cnt + 1; when "1100" => tx_frame <= '1'; tx_data_p <= tx_data_i1_d(11 downto 6); tx_data_n <= tx_data_q1_d(11 downto 6); tx_data_cnt <= tx_data_cnt + 1; when "1011" => tx_frame <= '0'; tx_data_p <= tx_data_i2_d(5 downto 0); tx_data_n <= tx_data_q2_d(5 downto 0); tx_data_cnt <= "100"; when "1010" => tx_frame <= '0'; tx_data_p <= tx_data_i2_d(11 downto 6); tx_data_n <= tx_data_q2_d(11 downto 6); tx_data_cnt <= tx_data_cnt + 1; when "1001" => tx_frame <= '1'; tx_data_p <= tx_data_i1_d(5 downto 0); tx_data_n <= tx_data_q1_d(5 downto 0); tx_data_cnt <= tx_data_cnt + 1; when "1000" => tx_frame <= '1'; tx_data_p <= tx_data_i1_d(11 downto 6); tx_data_n <= tx_data_q1_d(11 downto 6); tx_data_cnt <= tx_data_cnt + 1; when others => tx_frame <= '0'; tx_data_p <= "000000"; tx_data_n <= "000000"; tx_data_cnt <= tx_data_cnt + 1; end case; else tx_data_cnt <= "100"; tx_frame <= '0'; tx_data_p <= "000000"; tx_data_n <= "000000"; end if; end if; end process; ---------- RX_BUF/DDR ---------- -------------------------------- i_rx_clk_ibuf : IBUFGDS port map( I => rx_clk_in_p, IB => rx_clk_in_n, O => clk_ibuf_s );
i_clk_gbuf : BUFG port map( I => clk_ibuf_s, O => clk ); i_rx_frame_ibuf : IBUFDS port map( I => rx_frame_in_p, IB => rx_frame_in_n, O => rx_frame_ibuf_s );
i_rx_frame_iddr : IDDR generic map( DDR_CLK_EDGE => "SAME_EDGE_PIPELINED", INIT_Q1 => '0', INIT_Q2 => '0', SRTYPE => "ASYNC" ) port map( CE => '1', R => '0', S => '0', C => clk, D => rx_frame_ibuf_s, Q1 => rx_frame_p_s, Q2 => rx_frame_n_s );
g_rx: for l_inst in 0 to 5 generate i_rx_data_ibuf : IBUFDS port map( I => rx_data_in_p(l_inst), IB => rx_data_in_n(l_inst), O => rx_data_ibuf_s(l_inst) );
i_rx_data_iddr : IDDR generic map( DDR_CLK_EDGE => "SAME_EDGE_PIPELINED", INIT_Q1 => '0', INIT_Q2 => '0', SRTYPE => "ASYNC" ) port map( CE => '1', R => '0', S => '0', C => clk, D => rx_data_ibuf_s(l_inst), Q1 => rx_data_p_s(l_inst), Q2 => rx_data_n_s(l_inst) ); end generate g_rx; ---------- TX_BUF/DDR ---------- -------------------------------- i_tx_clk_oddr : ODDR generic map( DDR_CLK_EDGE => "SAME_EDGE", INIT => '0', SRTYPE => "ASYNC" ) port map ( CE => '1', R => '0', S => '0', C => clk, D1 => '0', D2 => '1', Q => tx_clk_oddr_s );
i_tx_clk_obuf : OBUFDS port map( I => tx_clk_oddr_s, O => tx_clk_out_p, OB => tx_clk_out_n );
i_tx_frame_oddr : ODDR generic map( DDR_CLK_EDGE =>"SAME_EDGE", INIT => '0', SRTYPE => "ASYNC" ) port map ( CE => '1', R => '0', S => '0', C => clk, D1 => tx_frame, D2 => tx_frame, Q => tx_frame_oddr_s );
i_tx_frame_obuf : OBUFDS port map( I => tx_frame_oddr_s, O => tx_frame_out_p, OB => tx_frame_out_n ); g_tx: for l_inst in 0 to 5 generate i_tx_data_oddr : ODDR generic map( DDR_CLK_EDGE => "SAME_EDGE", INIT => '0', SRTYPE => "ASYNC" ) port map ( CE => '1', R => '0', S => '0', C => clk, D1 => tx_data_p(l_inst), D2 => tx_data_n(l_inst), Q => tx_data_oddr_s(l_inst) );
i_tx_data_obuf : OBUFDS port map( I => tx_data_oddr_s(l_inst), O => tx_data_out_p(l_inst), OB => tx_data_out_n(l_inst) ); end generate g_tx; end Behavioral;
Что касается count, то он необходим для того, чтобы исключить запись в rx_data_i2_r2 и rx_data_q2_r2 неверных данных, когда rx_frame_s = "0000", но передачи как таковой уже нет; на прикрепленном рисунке эти данные выделены красным (на нем показана передача одних данных в течение 4 транзакций) Спасибо за ответы) в скором времени проверю это дело на плис и поделюсь результатами.
Причина редактирования: используйте теги для оформления кода (с) модератор
Эскизы прикрепленных изображений
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|