ovs_pavel 0 5 октября, 2012 Опубликовано 5 октября, 2012 · Жалоба Утро доброе. Коллеги, с приемом вроде бы разобрался (пакеты принимаются без сбоев), теперь отлаживаю передачу. Проходит без сбоев порядка 20% ... 30% информации. По аналогии с приемом сделал констрейны на передающие пины. Регистры поместил в IOB'ы: INST "U9/GM_TxD*" IOB = true ; INST "U9/GM_TxEn" IOB = true ; и задал фронты на выходных пинах: Net "Phy_TxD<?>" SLEW = FAST; Net "Phy_TxEn" SLEW = FAST; Ошибка заключается в "выпадении" некоторых битах, хотя на приемопередатчик байты данных и CRC идут правильно (ставил ФИФО - ловушку непосредственно на передаваемый пакет данных уже у самих выходных регистрах; обратным чтением прочитал - все отлично). Но на персоналку приходят пакеты с ошибками. Тактирую передающую часть частотой, той же самой, которая через буфер ODDR2 подается на Marvell 88E1111. Может ее надо пропустить через DCM с определенным сдвигом (больно Marvell капризен по времени установки)? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Beby 8 5 октября, 2012 Опубликовано 5 октября, 2012 · Жалоба По какому фронту TX_CLK, изменяются TX_EN и TX_D<*> ? Через какие триггера выдаются TX_CLK, TX_EN, TX_D<*> ? (можно кусок кода привести – глядишь еще чего заметим) И что-то я запамятовал: Какую ПЛИС используете Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ovs_pavel 0 5 октября, 2012 Опубликовано 5 октября, 2012 · Жалоба По какому фронту TX_CLK, изменяются TX_EN и TX_D<*> ? Через какие триггера выдаются TX_CLK, TX_EN, TX_D<*> ? (можно кусок кода привести – глядишь еще чего заметим) И что-то я запамятовал: Какую ПЛИС используете ПЛИС применяется Spartan6 - XC6SLX45. Схема формирования частот - следующая: 1. На ПЛИС приходит частота от внешнего генератора - 125МГц. 2. Эта частота подается на DCM, с помощью которого формируется две частоты - 125 МГц (проходит через CLK0) и 25 МГц (проходит через CLKFX) и далее эти эти частоты через BUFG и ODDR2 подаются на Marvell. Передающая часть также синхронизируется от частоты 125МГц полученной с модуля DCM и пропущенной через буфер BUFG. Ниже приводиться передающая часть. Данные в ФИФО набиваются от внешнего МП (стек TCP обрабатывается внешним контроллером; стек UDP обрабатывается внутри ПЛИС - видеопоток). Могу если интересно привести код CRC. module Frame_Prd ( //------------------------- Сигналы синхронизации. -------------------------// input Clk_125_MHz, // Тактовая частота 125 МГц. //--------------- Сигналы модуля управления интерфейсом AVR. ---------------// input Eth_ON, // Сигнал разрешения работы модуля (устанавливается AVR; активный уровень "1"). input [10:0] Len_Frm_Prd, // Длина передаваемого кадра (в байтах). input [31:0] FIFO_Prd_AVR, // Данные, предназначенные для передачи по интерфейсу Ethernet (предварительно записываются в ФИФО). input Wr_FIFO_Prd, // Сигнал разрешения записи в ФИФО передачи пакета. input Prd_PKG_Rdy, // Сигнал начала выдачи кадра. output reg Prd_PKG_Busy, // Сигнал активности операции передачи кадра (активный уровень "1"; выдается в регистр состояния AVR). //----------------------- Интерфейс Ethernet 1Gb/s. ------------------------// output [7:0] Phy_TxD, // output Phy_TxEn, // output Phy_TxEr, // //---------------------------- Тестовые сигналы. ---------------------------// output [7:0] test_Dout_FIFO, // Данные тестового ФИФО. input test_Clr_FIFO, // Сигнал сброса тестового ФИФО (запись в 62-ой регистр). input test_Rd_FIFO // Сигнал разрешения чтения тестового ФИФО (чтение 62-го регистра). ); //--------------------------------------------------------------------------// //--------------- Сигнал активности операции передачи кадра. ---------------// //--------------------------------------------------------------------------// reg Clr_PKG_Busy; // Сброс сигнала активности операции передачи кадра (также обнуляет ФИФО передачи кадра; на всякий случай). always @ (posedge Clk_125_MHz or posedge Clr_PKG_Busy) begin if (Clr_PKG_Busy) Prd_PKG_Busy <= 1'b0; else if (Prd_PKG_Rdy) Prd_PKG_Busy <= 1'b1; end //--------------------------------------------------------------------------// //------------------- Счетчик длины передаваемого кадра. -------------------// //--------------------------------------------------------------------------// reg Dec_Cnt_FRM; // Сигнал декремента счетчика длины передаваемого кадра. reg [10:0] Cnt_FRM; // Счетчик длины переданного кадра. always @ (posedge Clk_125_MHz or negedge Eth_ON) begin if (~Eth_ON) Cnt_FRM <= 11'd0; else if (Prd_PKG_Rdy) Cnt_FRM <= Len_Frm_Prd; else if (Dec_Cnt_FRM) Cnt_FRM <= Cnt_FRM - 1'd1; end //--------------------------------------------------------------------------// //-------------------------- ФИФО передачи кадра. --------------------------// //--------------------------------------------------------------------------// reg Rd_FIFO_Prd; // Сигнал чтения ФИФО передачи кадра. wire [31:0] w_FIFO_Prd; FIFO_Prd U1 ( .clk (Clk_125_MHz), .rst (Clr_PKG_Busy), .din (FIFO_Prd_AVR), .wr_en (Wr_FIFO_Prd), .rd_en (Rd_FIFO_Prd), .dout (w_FIFO_Prd), .full (), .empty () ); //--------------------------------------------------------------------------// //--------------- Счетчик числа переданных ниблов преамбулы. ---------------// //--------------------------------------------------------------------------// reg [2:0] Cnt_Pream; // Счетчик числа переданных ниблов преамбулы. reg Clr_Cnt_Pream; // Сброса счетчика числа переданных ниблов преамбулы. always @(posedge Clk_125_MHz or negedge Clr_Cnt_Pream) begin if (~Clr_Cnt_Pream) Cnt_Pream <= 3'd0; else Cnt_Pream <= Cnt_Pream + 1'b1; end //--------------------------------------------------------------------------// //------------ Управление мультиплексором ФИФО передачи данных. ------------// //--------------------------------------------------------------------------// // ФИФО 4-х байтное, а интерфейс Ethernet - байтовый. Поэтому необходимо // считывать слово данных один раз за 4 такта. reg [1:0] Cnt_MUX; // Счетчик управления мультиплексором ФИФО передачи данных. always @(posedge Clk_125_MHz or negedge Dec_Cnt_FRM) begin if (~Dec_Cnt_FRM) Cnt_MUX <= 2'd0; else Cnt_MUX <= Cnt_MUX + 1'b1; end //--------------------------------------------------------------------------// //------------------- Сигнал чтения ФИФО передачи кадра. -------------------// //--------------------------------------------------------------------------// always @ (posedge Clk_125_MHz or negedge Eth_ON) begin if (~Eth_ON) Rd_FIFO_Prd <= 1'b0; else Rd_FIFO_Prd <= (Cnt_MUX == 2'd2); end //--------------------------------------------------------------------------// //------------ Мультиплексор выбора данных ФИФО передачи кадра. ------------// //--------------------------------------------------------------------------// reg [7:0] Mux_FIFO_Prd; // Байт данных ФИФО передачи кадра. always @(Cnt_MUX or w_FIFO_Prd) begin case (Cnt_MUX) 2'd0: Mux_FIFO_Prd <= w_FIFO_Prd[31:24]; 2'd1: Mux_FIFO_Prd <= w_FIFO_Prd[23:16]; 2'd2: Mux_FIFO_Prd <= w_FIFO_Prd[15:8]; 2'd3: Mux_FIFO_Prd <= w_FIFO_Prd[7:0]; endcase end //--------------------------------------------------------------------------// //--------- Управление мультиплексором регистра контрольной суммы. ---------// //--------------------------------------------------------------------------// reg [1:0] Cnt_CRC; // Счетчик управления мультиплексором регистра контрольной суммы. always @(posedge Clk_125_MHz or posedge Dec_Cnt_FRM) begin if (Dec_Cnt_FRM) Cnt_CRC <= 2'd0; else Cnt_CRC <= Cnt_CRC + 1'b1; end //--------------------------------------------------------------------------// //-------- Мультиплексор выбора данных регистра контрольной суммы. ---------// //--------------------------------------------------------------------------// reg [7:0] Mux_KS; // Байт данных регистра контрольной суммы. wire [31:0] Rg_CRC; // Регистр контрольной суммы. always @(Cnt_CRC or Rg_CRC) begin case (Cnt_CRC) 3'd0: Mux_KS <= ~Rg_CRC[7:0]; 3'd1: Mux_KS <= ~Rg_CRC[15:8]; 3'd2: Mux_KS <= ~Rg_CRC[23:16]; 3'd3: Mux_KS <= ~Rg_CRC[31:24]; endcase end //--------------------------------------------------------------------------// //------------------ Выходной мультиплексор выбора данных. -----------------// //--------------------------------------------------------------------------// // Мультиплексирует данные преамбулы, начала кадра, ФИФО передачи и регистра // контрольной суммы. reg [1:0] Upr_D; // Регистр управления выходным мультиплексором выбора данных. reg [7:0] Mux_D; always @(Upr_D or Mux_FIFO_Prd or Mux_KS) begin case (Upr_D) 2'd0: Mux_D <= 8'b01010101; 2'd1: Mux_D <= 8'b11010101; 2'd2: Mux_D <= Mux_FIFO_Prd; 2'd3: Mux_D <= Mux_KS; endcase end //--------------------------------------------------------------------------// //---------------- Объявление регистров автомата состояний. ----------------// //--------------------------------------------------------------------------// reg Rg_TxEn; // Сигнал передачи действительных данных. //--------------------------------------------------------------------------// //--------------------- Объявление автомата состояний. ---------------------// //--------------------------------------------------------------------------// reg [2:0] CState; parameter [2:0] CS_Idle = 3'd0, CS_Pream = 3'd1, CS_SOF = 3'd2, CS_Data = 3'd3, CS_CRC = 3'd4, CS_End = 3'd5; //--------------------------------------------------------------------------// //--------------------------- Автомат состояний. ---------------------------// //--------------------------------------------------------------------------// always @ (posedge Clk_125_MHz or negedge Eth_ON) begin if (~Eth_ON) begin CState <= CS_Idle; Rg_TxEn <= 1'b0; // Сигнал передачи действительных данных. Clr_Cnt_Pream <= 1'b0; // Сброса счетчика числа переданных ниблов преамбулы. Dec_Cnt_FRM <= 1'b0; // Сигнал декремента счетчика длины передаваемого кадра. Clr_PKG_Busy <= 1'b0; // Сброс сигнала активности операции передачи кадра (также обнуляет ФИФО передачи кадра; на всякий случай). Upr_D <= 2'd0; // Регистр управления выходным мультиплексором выбора данных. end else begin case (CState) CS_Idle: // ОЖИДАНИЕ СИГНАЛА НАЧАЛА ВЫДАЧИ КАДРА. begin if (Prd_PKG_Rdy) begin CState <= CS_Pream; Rg_TxEn <= 1'b1; Clr_Cnt_Pream <= 1'b1; end else CState <= CS_Idle; end CS_Pream: // ФОРМИРОВАНИЕ ПРЕАМБУЛЫ. begin if (Cnt_Pream == 3'd6) begin CState <= CS_SOF; Clr_Cnt_Pream <= 1'b0; Upr_D <= 2'd1; end else CState <= CS_Pream; end CS_SOF: // ФОРМИРОВАНИЕ СОСТОЯНИЯ "SOF". begin CState <= CS_Data; Upr_D <= 2'd2; Dec_Cnt_FRM <= 1'b1; end CS_Data: // ВЫДАЧА ДАННЫХ. begin if (Cnt_FRM == 11'd1) begin CState <= CS_CRC; Upr_D <= 2'd3; Dec_Cnt_FRM <= 1'b0; end else CState <= CS_Data; end CS_CRC: begin if (Cnt_CRC == 2'd3) begin CState <= CS_End; Rg_TxEn <= 1'b0; Upr_D <= 2'd0; Clr_PKG_Busy <= 1'b1; end else CState <= CS_CRC; end CS_End: begin CState <= CS_Idle; Clr_PKG_Busy <= 1'b0; end default: begin CState <= CS_Idle; Rg_TxEn <= 1'b0; Clr_Cnt_Pream <= 1'b0; Dec_Cnt_FRM <= 1'b0; Clr_PKG_Busy <= 1'b0; Upr_D <= 2'd0; end endcase end end //--------------------------------------------------------------------------// //-------------- Привязка выходных данных к тактовой частоте. --------------// //--------------------------------------------------------------------------// reg GM_TxEn; reg [7:0] GM_TxD; always @ (posedge Clk_125_MHz or negedge Eth_ON) begin if (~Eth_ON) begin GM_TxEn <= 1'b0; GM_TxD <= 8'd0; end else begin GM_TxEn <= Rg_TxEn; GM_TxD <= Mux_D; end end assign Phy_TxD = GM_TxD; assign Phy_TxEn = GM_TxEn; //--------------------------------------------------------------------------// //------ Модуль вычисления CRC пакета передаваемого по сети Ethernet. -------// //--------------------------------------------------------------------------// wire [31:0] w_Rg_CRC; my_crc_prd U2 ( .Clk_125_MHz (Clk_125_MHz), .Eth_ON (Eth_ON), .Clr_CRC (Clr_PKG_Busy), .D_In (Mux_FIFO_Prd), .En_CRC (Dec_Cnt_FRM), .Rg_CRC (w_Rg_CRC) ); assign Rg_CRC = w_Rg_CRC; //--------------------------------------------------------------------------// //--------------------- Назначение выходных сигналов. ----------------------// //--------------------------------------------------------------------------// assign Phy_TxEr = 1'b0; //--------------------------------------------------------------------------// //-------------------------- ФИФО передачи кадра. --------------------------// //--------------------------------------------------------------------------// wire [7:0] w_test_fifo; test_fifo U_test ( .clk (Clk_125_MHz), .rst (test_Clr_FIFO), .din (Mux_D), .wr_en (Rg_TxEn), .rd_en (test_Rd_FIFO), .dout (w_test_fifo), .full (), .empty () ); assign test_Dout_FIFO = w_test_fifo; endmodule Да, забыл, все тактируется положительным фронтом сигнала 125МГц. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Beby 8 5 октября, 2012 Опубликовано 5 октября, 2012 · Жалоба ПЛИС применяется Spartan6 - XC6SLX45. Схема формирования частот - следующая: 1. На ПЛИС приходит частота от внешнего генератора - 125МГц. 2. Эта частота подается на DCM, с помощью которого формируется две частоты - 125 МГц (проходит через CLK0) и 25 МГц (проходит через CLKFX) и далее эти эти частоты через BUFG и ODDR2 подаются на Marvell. Передающая часть также синхронизируется от частоты 125МГц полученной с модуля DCM и пропущенной через буфер BUFG. 1. Попробуйте сделать вот такие времянки для TX GMII интерфейса: Этот вариант должен помочь со стабильность передачи данных в Eth Phy. В Вашем исходнике я не заметил constaint'ов IOB для GM_TxD, GM_TxEn, если этих constaint'ов нет где-то в другом месте, то их необходимо добавить. 2. 88E1111 имеет очень жесткие требования к XTAL1, и меня берут жестокие сомнения, что после пропускания CLK через DCM получится что-то подходящее. Поэтому предлагаю 2 выхода: 1) завести на XTAL1 первородный входной Clock, который вы сейчас подаёте на DCM - в этом случае 88E1111 получит наиболее чистый clock. Правда для этого прийдётся ногу SEL_FREQ посадить на землю. 2) поделить входной Clock (не прошедший DCM) на триггерах и через ODDR (тактируемую первородным входным Clock'ом) выдать наружу. На всякий случай посоветую еще раз внимательно просмотреть раздел XTAL1 Input Clock Timing 88E1111 Datasheet - особенно с три сноски внизу. 3. Для работы с 88E1111 GMII/RGMII я использовал Spartan-3A/Virtex-5/Virtex-6, и во всех случаях для всех сигналов использовал LVCMOS25, Drive=8,12, Slew=slow - так меньше звона стоит в линиях. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ovs_pavel 0 5 октября, 2012 Опубликовано 5 октября, 2012 · Жалоба 1. Попробуйте сделать вот такие времянки для TX GMII интерфейса: Этот вариант должен помочь со стабильность передачи данных в Eth Phy. В Вашем исходнике я не заметил constaint'ов IOB для GM_TxD, GM_TxEn, если этих constaint'ов нет где-то в другом месте, то их необходимо добавить. 2. 88E1111 имеет очень жесткие требования к XTAL1, и меня берут жестокие сомнения, что после пропускания CLK через DCM получится что-то подходящее. Поэтому предлагаю 2 выхода: 1) завести на XTAL1 первородный входной Clock, который вы сейчас подаёте на DCM - в этом случае 88E1111 получит наиболее чистый clock. Правда для этого прийдётся ногу SEL_FREQ посадить на землю. 2) поделить входной Clock (не прошедший DCM) на триггерах и через ODDR (тактируемую первородным входным Clock'ом) выдать наружу. На всякий случай посоветую еще раз внимательно просмотреть раздел XTAL1 Input Clock Timing 88E1111 Datasheet - особенно с три сноски внизу. 3. Для работы с 88E1111 GMII/RGMII я использовал Spartan-3A/Virtex-5/Virtex-6, и во всех случаях для всех сигналов использовал LVCMOS25, Drive=8,12, Slew=slow - так меньше звона стоит в линиях. Да, к сожалению ногу SEL_FREQ на землю посадить не удаться, т.к. корпус BGA (с многослойкой это проблемы). Вот не думал, что DCM так может сорить? Судя по вашим времянкам, вы работаете от отрицательного фронта (либо подгоняете фронт под данные, т.к. после клока - падающего фронта, время установи данных равно практически 0). А в чем симулите - моделсим? Просто я с 12-ой версии айса симулю его встроенным, вроде как от моделсима отошел. Спасибо за советы, буду пробовать. Отпишусь что получилось. Насчет констрейнов - я их добавил в файл .usf, т.е. с констрейнами все нормально. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Beby 8 5 октября, 2012 Опубликовано 5 октября, 2012 · Жалоба Да, к сожалению ногу SEL_FREQ на землю посадить не удаться, т.к. корпус BGA (с многослойкой это проблемы). Вот не думал, что DCM так может сорить?Я скажу по другому - он не может выдавать чистый сигнал. Если входной сигнал совсем поганый - то DCM его хорошенько почистит,.. а если входной сигнал чистый, то, соответственно, несколько испоганит. Но тут вопрос не столько в DCM, сколько в жёстких требованиях 88E1111 - у них, похоже, система чувствительна в jitter'у определённой частоты, т.е. во времена разработки 88E1111 явно предполагалось, что к ней будет подвешен кварц, а частоту будут брать уже с 88E1111 для своих целей - и нога для этого есть специальная. И я её даже пользовал в проекте со Spartan-3A: 88E1111 из 25МГц делал весьма чистенькие 125МГц. Судя по вашим времянкам, вы работаете от отрицательного фронта (либо подгоняете фронт под данные, т.к. после клока - падающего фронта, время установи данных равно практически 0). А в чем симулите - моделсим?Да, ModelSim. На самом деле всё у меня работает тоже по положительному фронту... просто GTX_CLK выдаётся инверсным (на ODDR 1 и 0 на D местами поменяны). Насчет констрейнов - я их добавил в файл .usf, т.е. с констрейнами все нормально.Это хорошо. Но на будущее, моя практика показала, что лучше такие constaint'ы добавлять прямо в код - тогда код лучше (грамотнее) XST синтезируется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться