реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> трансивер ad_9361 + Zynq (Интерфейс LVDS)
Alexey_pashinov
сообщение Feb 1 2015, 13:31
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 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;
Go to the top of the page
 
+Quote Post
Timmy
сообщение Feb 2 2015, 08:31
Сообщение #2


Знающий
****

Группа: Участник
Сообщений: 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.
Go to the top of the page
 
+Quote Post
Alexey_pashinov
сообщение Feb 2 2015, 11:02
Сообщение #3


Участник
*

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



В том примере, который они приводитят (axi_ad9361_dev_if.v) реализовано выделение из данных rx_data_in_p(n) мнимой и действительной частей сигнала, выходящих с ацп. (в Вашем примере придется писать все самому, да и зачем, если AD приводит примеры)). Вопрос же что делать с сигналами delay control, как с ними работать применительно к данной микросхеме?
Go to the top of the page
 
+Quote Post
Timmy
сообщение Feb 2 2015, 11:44
Сообщение #4


Знающий
****

Группа: Участник
Сообщений: 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, чтобы оно как-то работало на определённом чипе при определённой температуре и напряжении. Или даже не подгонять, скорее всего и так заработает, это стандартная китайская технологияsm.gif. А по-хорошему - это xapp860.
Go to the top of the page
 
+Quote Post
bogaev_roman
сообщение Feb 2 2015, 12:00
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
Alexey_pashinov
сообщение Feb 2 2015, 12:46
Сообщение #6


Участник
*

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



Спасибо за советы sm.gif Попробую все таки пока поработать с axi_ad9361_dev_if.v и проверить его работу, а дальше по обстоятельствам.
Go to the top of the page
 
+Quote Post
Alexey_pashinov
сообщение Feb 5 2015, 15:10
Сообщение #7


Участник
*

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



Решил последовать примеру bogaev_roman'a и переработать предложенный экземпл. Убрал все элементы задержки и переписал с неудобного мне верилога на vhdl. Вопрос сначала про передачу. В прикрепленном файле показана диаграмма передачи последовательно двух наборов данных. Для передачи каждого набора данных выставляется свой valid, получается при начале второй транзакции сначала выставляется valid и в это время передаются нулевые данные, а после только идут данные на передачу, эта ситуация на рис отмечена красным. В UG приводят диаграмму где данные идут друг за другом и там нет промежуточных нулевых данных, как получить похожую диаграмму?

Было бы здорово, если кто поделился времянками)

Сообщение отредактировал Alexey_pashinov - Feb 5 2015, 15:12
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
bogaev_roman
сообщение Feb 6 2015, 09:45
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 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).
Go to the top of the page
 
+Quote Post
Alexey_pashinov
сообщение Feb 6 2015, 10:04
Сообщение #9


Участник
*

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



Повнимательней просмотрел ваш код и увидел что вы не используете сигнал начала передачи valid, который был в примере. Я его использовал, поэтому перед тем как попасть в автомат, формирующий данные и сигнал фрейм, нужно дождаться условия valid = '1'. Собственно из за этого и были задержки в один такт между двумя похождениями автомата. В общем уберу этот сигнал) спасибо за ваш ответ и еще был вопрос по rx, если тогда не решу проблему выложу времянки в понедельник)
Go to the top of the page
 
+Quote Post
bogaev_roman
сообщение Feb 6 2015, 10:41
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 088
Регистрация: 20-10-09
Из: Химки
Пользователь №: 53 082



Цитата(Alexey_pashinov @ Feb 6 2015, 13:04) *
и еще был вопрос по rx

А что там по rx, просто обратный процесс сборки данных исходя из последовательности состояний frame, выходные данные обновляются раз в 4 такта частоты ADC_clk. Времянку привести сейчас проблематично - чипскопом к входным сигналам до DDR не подцепиться, а моделированием этого куска я не занимался. Единственное - чтобы времянки не поползли и не было временных сбоев я rx_clk_in_p(n) сдвинул на 345 градусов и вся регистровая логика работает от этого сдвинутого сигнала ADC_clk (но тут можно просто временные ограничения задать на входные сигналы).
Go to the top of the page
 
+Quote Post
Alexey_pashinov
сообщение Feb 10 2015, 06:58
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 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 транзакций)

Спасибо за ответы) в скором времени проверю это дело на плис и поделюсь результатами.
Причина редактирования: используйте теги для оформления кода (с) модератор

Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 23:31
Рейтинг@Mail.ru


Страница сгенерированна за 0.01435 секунд с 7
ELECTRONIX ©2004-2016