Взаимодействие через ethernet на примере отладочной платы Xilinx с чипом Virtex 7

Для проведения исследовательских работ с использованием отладочной платы Xilinx VC707 бывает необходимо осуществить сопряженние персонального компьютера с этим устройством через интерфейс ethernet. В результате поиска в интернете сведений о подобных проектах, были найдены ресурсы opencores.org/ и www.ohwr.org/projects. На них выложено большое количество IP core с исходным кодом.

Разработка модуля приема/передачи информации через интерфейс ethernet.

Для обеспечения взаимодействия отладочной карты и персонального компьютера реализацию большей части Ethernet/IP протоколов можно не выполнять. Так как персональный компьютер физически подключен к отладочной плате, достаточно реализовать прием/передачу кадра формата IEEE802. Для того, чтобы программно передавать и принимать такие кадры используется библиотека WinPcap (http://www.winpcap.org/install/default.htm).
На плате VC707 используется Marvell Alska PHY (88E11111) для взаимодействия через интерфейс Ethernet 10, 100, или 1000 Mb/s. Плата поддерживает только режим SGMII. Физическое соединение с кабелем осуществляется через Halo HFJ11-1G01E RJ-45 соединитель со встроенными магнитами (Рис. 1).


Рис. 1: Оранизация подключения через интерфейс Ethernet на отладочной плате

При включении или сбросе, PHY конфигурируется для работы в режиме SGMII с адресом 0b0111. Настройки могут быть модифицированы командами, передаваемыми через интерфейс MDIO. В таблице 1 приведена информация о подключении выводов FPGA к PHY.

Таблица 1: Соединение Ethernet, FPGA к устройству PHY


Для реализации приема/передачи данных по ethernet на ПЛИС в качестве отправной точки был выбран проект «10_100_1000 Mbps tri-mode ethernet MAC»opencores.org/project,ethernet_tri_mode. Из него была заимствована и переделана часть кода, обеспечивающая логическое формирование кадра данных.

1 Структура пакета Ethernet

Пакет представлен на Рис 2.

Рис. 2: Формат кадра

PREAMBLE (Преамбула): стартовая комбинация, состоящая из последовательности чередующихся нулей и единиц. Необходима для настройки аппаратуры адаптера или другого сетевого устройства на прием и обработку пакета.

SOF (Start-of-frame Delimiter, Разделитель начала кадра): двоичная последовательность 10101011, которая служит для разделения преамбулы и следующего за ним поля, а также для окончательной синхронизации приемных станций двумя младшими битами (Стандарт IEЕЕ 802.3).

DESTINATION ADDRESS/SOURCE ADDRESS: (Адрес Ethernet/МАС-адрес) состоит из 12 шестнадцатеричных цифр (48 битов / 6 байтов). Первые 6 цифр МАС-адреса содержат идентификатор производителя (код поставщика – vendor code), который также называют Organizational Unique Identifier (OUI), назначаемый IEEE. Последние 6 цифр назначаются производителем и часто представляют собой серийный номер. Данная структура адреса обеспечивает абсолютную уникальность сетевых устройств.

LENGTH Размер передаваемых в пакете данных.
Минимальный размер фреймов Ethernet требует, чтобы размер данных был хотя бы 46 байт.
Предпосылок на введение верхнего ограничения размера фрейма было несколько:
  • Задержка при передаче – чем больше фрейм, тем дольше длится передача. Для ранних сетей, где Collision домен не ограничивался портом, и все станции должны были ждать завершения передачи, это было серьёзной проблемой.
  • Чем больше фрейм, тем больше вероятность того что фрейм при передаче будет поврежден, что приведет к необходимости повторной передачи, и все устройства в collision домене будут вынуждены опять ожидать.
  • Ограничения, накладываемые памятью используемой под интерфейс буферы – на тот момент (1979г) увеличение буферов значительно удорожало стоимость интерфейса.
  • Ограничение, вносимое полем Length/Type – в стандарте закреплено, что все значения выше 1536 (от 05-DD до 05-FF.) указывают на EtherType, соответственно длина должна быть меньше 05-DC.

2 Разработка модуля передатчика


module IEEE802TX(	 
     input Reset,
     input Clk,
     input clk_en,

     output [7:0]  gmii_txd,              // Transmit data from client MAC.   
     output        gmii_tx_en,            // Transmit control signal from client MAC.
     output        gmii_tx_er,            // Transmit control signal from client MAC.
	  
     // parameter for Fifo
     input iEmpty,                        // fifo is empty
     input [7:0] i8Data,              // data from fifo
     output oRead,                    // read request for data from fifo
);

Приведем назначение сигналов:


При передаче информации через ethernet выделяются следующие состояния:
  • StateIdle. Состояние ожидания данных для передачи.
  • StatePreamble. Передача преамбулы.
  • StateSFD. Передача октета — разделителя данных.
  • StateHeader. Передача заголовка кадра IEEE802.
  • StateData. Передача данных.
  • StateFCS. Передача контрольной суммы.
  • StateIFG. Межкадровый интервал.
Упрощенная схема автомата состояний передатчика пакета представлена на рис. 3.

Рис. 3: Упрощенная диаграмма состояний модуля передатчика пакета данных.
Исходное состояние IDLE. Как только на входе модуля появляются данные для передачи, они записываются в память типа FIFO (на диаграмме не указано) и модуль переходит в режим передачи преамбулы (состояние PREAMBLE). После передачи преамбулы осуществляется передача октета SFD. Затем передается заголовок, содержащий MAC адрес приемника и передатчика (состояние HEADER). После этого из памяти FIFO начинается передача данных в сотоянии DATA. Передача данных завершается либо при опустошении буфера FIFO, либо при достижении предельного размера кадра. Для всех переданных данных подсчитывается контрольная сумма и передается на стадии FCS. На этом работа передающего завершается и после паузы (состояние IFG) модуль переходит в состояние IDLE. Далее описанные процессы повторяются.
Основной конечный автомат описывается следующим кодом на Verilog:

	always @(posedge Clk)
		if (Reset)
			state <= StateIdle;
		else if (clk_en)
			state <= next_state;  
			
	always @(*)
		case (state)  // synopsys full_case
			StateIdle:	 
			begin
				next_state <= state;
			    if (~iEmpty)
					next_state <= StatePreamble;
			end
			StatePreamble: 
			begin				  
				next_state <= state;
				if (wFinishPreamble)
					next_state <= StateSFD;
			end
			StateSFD:  
				next_state <= StateHeader;
			StateHeader:  
			begin
					next_state <= state;
					if (wFinishHeader)
						next_state <= StateData;
			end
			StateData:
			begin
			    next_state <= state;
				if (~wReadFifo | wFinishData)
					next_state <= StateFCS;
			end
			StateFCS:	
			begin
				next_state <= state;
				if (FCS_end)
			    	next_state <= StateIFG;
			end
			StateIFG:											  
			begin
				next_state <= state;
				if (r6IFG_counter==6'd12)//remove some additional time
					next_state <= StateIdle;	
			end
		endcase


3 Разработка модуля приемника

Интерфейсный модуль, осуществляющий прием данных, имеет следующий заголовок

module IEEE802RX(
      input        Reset,
      input        Clk,
      input  [7:0]  gmii_rxd,
      input         gmii_rx_dv,
      input         gmii_rx_er,
      input         clk_en,
		
     // output module
     output reg oBeginPacket,
     output reg oEndPacket,
     output reg oOkCRC,
     output  [7:0] o8PacketData,
     output    oValidData
     );


Назначение сигналов следующее:

При приеме информации через ethernet выделяются следующие состояния:
  • State_idle. Состояние простоя. Ожидание принимаемых данных.
  • State_preamble. Синхронизация по преамбуле.
  • State_SFD. Принят октет — разделитель данных.
  • State_data. Состояние приема данных пакета.
  • State_checkCRC. Проверка контрольной суммы.
  • State_OkEnd. Прием завершен.
  • State_drop. Прекрашение анализа текущего кадра.
  • State_ErrEnd. Ошибка при приеме данных.
  • State_CRCErrEnd. Ошибка контрольной суммы.
  • State_IFG. Межкадровый интервал.

Упрощенная схема автомата состояний приемника пакета представлена на рис. 4.
Первоначально модуль находится в состоянии IDLE. Как только на вход приемника начинают поступать данные, модуль переходит в состояние PREAMBLE. В этом состоянии осуществляется прием октетов 0x55. Как только на вход приходит октет oxd5, модуль переводится в состояние SFD, после которого начинается прием данных (состояние DATA). Прием данных осуществляется до тех пор, пока либо есть принимаемые данные, либо превышен допустимый размер принимаемого пакета. Принимаемые данные содержат MAC адреса приемника и передатчика, данные пользователя. Если превышен размер пакета, модуль переводится в состояние Drop. Если же данные корректны, проверяется CRC сумма принятых данных и, в зависимости от результата проверки, модуль переводится либо в состояние okEnd (в случае успешной проверки), либо в состояние ErrEnd (в случае несоответствия CRC суммы данных). Затем модуль не осуществляет никаких операций (состояние IFG), после чего переходит в исходное состояние IDLE. Далее описанные выше процессы вновь повторяются.


Рис. 4: Упрощенная диаграмма состояний модуля приемника пакета данных

Основной конечный автомат описывается следующим кодом на Verilog:

always @ (posedge Clk)                 
    if (Reset)                                          
        Current_state   <= State_idle;                   
    else  if (clk_en)                                  
        Current_state   <= Next_state;      	
	
always @ (*)  
        case (Current_state) 
        State_idle:
		            if (gmii_rx_dv&&gmii_rxd == 8'h55)
				        Next_state = State_preamble;  
		            else
				        Next_state  = Current_state; 
        State_preamble:                             
                    if (!gmii_rx_dv)                        
                        Next_state = State_ErrEnd;      
                    else if (gmii_rx_er)                     
                        Next_state = State_drop;        
                    else if (gmii_rxd == 8'hd5)                  
                        Next_state = State_SFD;                 
                    else if (gmii_rxd== 8'h55)                
                        Next_state  = Current_state;     
                    else                                
                        Next_state  = State_drop; 	
        State_SFD:                                  
                    if (!gmii_rx_dv)                        
                        Next_state  = State_ErrEnd;      
                    else if (gmii_rx_er)                     
                        Next_state  = State_drop;        
                    else                                
                        Next_state  = State_data; 	
        State_data:                                
                    if (!gmii_rx_dv&&!rToo_short&&!rToo_long)                        
                        Next_state  = State_checkCRC;   
                    else if (!gmii_rx_dv&&(rToo_short||rToo_long))
                        Next_state  = State_ErrEnd;
                    else if (gmii_rx_er||rToo_long)                     
                        Next_state  = State_drop;        
                    else                                
                        Next_state  = State_data; 
        State_checkCRC:
                     if (wCRC_err)
                        Next_state  = State_CRCErrEnd;
                     else
                        Next_state  = State_OkEnd;								
		State_drop:                                 
                    if (!gmii_rx_dv)                        
                        Next_state  = State_ErrEnd;      
                    else                                
                        Next_state  = Current_state;  
		State_OkEnd:                                
                        Next_state  = State_IFG;         
        State_ErrEnd:                               
                        Next_state  = State_IFG; 
        State_CRCErrEnd:                               
                        Next_state  = State_IFG; 
        State_IFG:                                  
                    if (r6IFG_counter==6'd12)   //remove some additional time     
                        Next_state  = State_idle;        
                    else                                
                        Next_state  = Current_state; 								
		default:
		           Next_state  = State_idle;    
		endcase

4 Среда ActiveHDL

На официальном сайте www.aldec.com/en/products/fpga_simulation/active_hdl_student представлена версия Active-HDL Student Edition, которую студенты могут свободно использовать в учебных целях.
Информацию по среде можно получить как на официальном сайте производителя, так и на многочисленных ресурсах в сети Интернет, например www.kit-e.ru/articles/circuit/2009_03_134.php.
Для проверки работоспособности разработанных модулей разработаны тестовые модули.
Для проверки работоспособности разработанных модулей на вход передатчика подадим сигнал в виде последовательности сигналов, кодирующих арифметическую последовательность чисел. Программа ная языке описания аппоаратуры Verilog приведена ниже.
Модуль генерации сигнала.

`timescale 1ns / 1ps
module test_signal_generator(reset, clk, data_valid, data8);

input reset;
input clk;
output data_valid;

output [7:0] data8;

reg enable = 1'b0;

reg data_valid = 1'b0;
wire[7:0] data8;

reg [3:0] cntr_delay = 4'd0;
always @(posedge clk)
	if (reset)	  
	begin
		enable <= 1'b0;
		cntr_delay <= 4'd0;
	end else if (cntr_delay == 4'd3)
	begin			   
		enable <= 1'b1;
	end
	else
		cntr_delay <= cntr_delay + 1'b1;

reg [7:0] r8Counter = 8'd1;
assign data8 = r8Counter;





	always @(posedge clk)
	if (reset)
		data_valid <= 1'b0;
	else if (enable)
		if (r8Counter == 8'd255)
			data_valid <= 1'b0;
		else
			data_valid <= 1'b1;
			
always @(posedge clk)
   if (reset)
      r8Counter <= 8'd1;
	else if (data_valid)
		begin
			if (r8Counter == 8'd255)
				r8Counter <= 8'd255;
			else 
				r8Counter <= r8Counter + 1'b1;
		end
	
endmodule

Модуль верхнего уровня обеспечивает соединение генератора сигналов, модуля передатчика и приемника.

`timescale 1ns / 1ps
module test_bench(reset, clk, data_valid, data8, gmii_txd, gmii_tx_en);

input reset;
input clk;
output data_valid;
output [7:0] data8;

output [7:0]  gmii_txd;              // Transmit data from client MAC.
output        gmii_tx_en;            // Transmit control signal from client MAC.
wire        gmii_tx_er;            // Transmit control signal from client MAC.

wire reset;
wire clk;
wire data_valid;
wire [7:0] data8;

glbl glbl();

test_signal_generator signal(reset, clk, data_valid, data8);

wire [7:0] fifo_out8;
wire fifo_empty;
wire fifo_read;
//wire fifo_write;

fifo8x512	fifo8x512_inst (
	.clk ( clk ),
	.rst (reset),
	.din ( data8 ),
	.rd_en ( fifo_read ),
	.wr_en ( data_valid ),
	.empty ( fifo_empty ),
	.full (  ),
	.dout ( fifo_out8 )
	);

	wire [10:0]   i11MTU = 11'd100;
	
	
IEEE802TX IEEE802TX_inst(	 
	.Reset(reset),
	.Clk(clk),
	.clk_en(1'b1),
	.gmii_txd(gmii_txd),              // Transmit data from client MAC.
   .gmii_tx_en(gmii_tx_en),            // Transmit control signal from client MAC.
   .gmii_tx_er(gmii_tx_er),            // Transmit control signal from client MAC.
	  
   // parameter for Fifo
	.iEmpty(fifo_empty),                        // fifo is empty
	.i8Data(fifo_out8),                  // data from fifo
	.oRead(fifo_read),                    // read request for data from fifo
	// parameter for MTU
	.i11MTU(i11MTU)
	  
	  );	
	 
	  
	  wire [7:0] w8Data;
	  wire wDataValid;
	  wire wBeginPacket;
	  wire wEndPacket;
	  wire wOkCRC;
	  
	  ReceiveData ReceiveData_inst(
      .Reset(reset),
	  .SysClk(clk),
	  .Clk(clk),
      .gmii_rxd(gmii_txd),
      .gmii_rx_dv(gmii_tx_en),
      .gmii_rx_er(gmii_tx_er),
      .clk_en(1'b1),
		
		// Данные на LCD
		.oLine1(),
		.oLine2(),
		
		// Выходные данные
		.o8Data(w8Data),
		.oDataValid(wDataValid),
		.oBeginPacket(wBeginPacket),
		.oEndPacket(wEndPacket),
		.oOkCRC(wOkCRC)
    );
endmodule

Диаграмма передачи пакета данных представлена на рис. 5 и рис. 6.

Рис. 5: Временная диаграмма начала передачи пакета с данными

Рис. 6: Временная диаграмма конца передачи пакета с данными
5 Реализация на Xilinx VC707

Для реализации модуля приемника/передатчика сформируем IP с использованием CORE Generator.

Рис. 7: Мастер генерации ядра. Шаг 1.

Рис. 8: Мастер генерации ядра. Шаг 2.

Рис. 9: Мастер генерации ядра. Шаг 3.

Рис. 10: Мастер генерации ядра. Шаг 4.

Модуль, формирующий сигналы подключения сформированного IP (gig_eth_pcs_pma_v11_2_block) к разработанным модулям передатчика и приемника gmii.v.

module gmii(
// asynchronous reset
      input         glbl_rst,

      // 200MHz clock input from board
      //input         clk_in_p,
      //input         clk_in_n,
      input         clk_200_bufg,
      output        phy_resetn,
     
     //added SGMII serial data and reference clock ports
      input            gtrefclk_p,            // Differential +ve of reference clock for MGT: 125MHz, very high quality.
      input            gtrefclk_n,            // Differential -ve of reference clock for MGT: 125MHz, very high quality.
      output           txp,                   // Differential +ve of serial transmission from PMA to PMD.
      output           txn,                   // Differential -ve of serial transmission from PMA to PMD.
      input            rxp,                   // Differential +ve for serial reception from PMD to PMA.
      input            rxn,                   // Differential -ve for serial reception from PMD to PMA.
      
      output           synchronization_done,
      output           linkup,
		
		      // GMII Interface
      //---------------
      output        sgmii_clk_en,          
      input [7:0]  gmii_txd,
      input        gmii_tx_en,
      input        gmii_tx_er,
      output  [7:0]  gmii_rxd,
      output         gmii_rx_dv,
      output         gmii_rx_er,
      output         userclk2

    );

//----------------------------------------------------------------------------
   // internal signals used in this top level wrapper.
   //----------------------------------------------------------------------------
  // Extra registers to ease IOB placement
   wire  [15:0]  status_vector_int;
	wire [4:0] configuration_vector;
  assign synchronization_done = status_vector_int[1];
   assign linkup = status_vector_int[0];
  
     // clock generation signals for tranceiver
     wire         gtrefclk;                 // gtrefclk routed through an IBUFG.
     wire         txoutclk;                 // txoutclk from GT transceiver.
     wire         txoutclk_bufg;            // txoutclk from GT transceiver routed onto global routing.
     wire         resetdone;                // To indicate that the GT transceiver has completed its reset cycle
     wire         mmcm_reset;               // MMCM reset signal.
     wire         clkfbout;                 // MMCM feedback clock
     wire         clkout0;                  // MMCM clock0 output (62.5MHz).
     wire         clkout1;                  // MMCM clock1 output (125MHz).
     wire         userclk;                  // 62.5MHz clock for GT transceiver Tx/Rx user clocks
     //wire         userclk2;                 // 125MHz clock for core reference clock.
  
     (* ASYNC_REG = "TRUE" *)
     reg   [3:0]  pma_reset_pipe;           // flip-flop pipeline for reset duration stretch
  
     wire         pma_reset;                // Synchronous transcevier PMA reset
	  
	  // clock generation signals for SGMII clock
     wire         sgmii_clk_r;              // Clock to client MAC (125MHz, 12.5MHz or 1.25MHz) (to rising edge DDR).
     wire         sgmii_clk_f;              // Clock to client MAC (125MHz, 12.5MHz or 1.25MHz) (to falling edge DDR).
  
     // GMII signals
     wire         gmii_isolate;             // internal gmii_isolate signal.
     wire         speed_is_10_100;
     wire         speed_is_100;
	  
	  assign       speed_is_10_100 = (status_vector_int[11:10] == 2'b10) ? 1'b0 : 1'b1;
	  assign       speed_is_100 = (status_vector_int[11:10] == 2'b01) ? 1'b1 : 1'b0;
	  
	  

     reg                  phy_resetn_int;

	  // resets (and reset generation)
	  wire                 dcm_locked;
	  wire                 glbl_rst_int;
     reg   [5:0]          phy_reset_count;
     wire                 glbl_rst_intn;

	wire                 chk_reset_int;
   reg                  chk_pre_resetn = 0;
   reg                  chk_resetn = 0;
   wire                 gtx_clk_reset_int;
   reg                  gtx_pre_resetn = 0;
   reg                  gtx_resetn = 0;


// Auto-Negotiation Link Timer value
     wire [8:0] link_timer_value;
     wire       an_interrupt;
     wire[15:0] an_adv_config_vector;
     wire       an_restart_config;
     wire signal_detect;

     //---------------
     // global reset
   reset_sync glbl_reset_gen (
      .clk              (userclk2),
      .enable           (dcm_locked),
      .reset_in         (glbl_rst),
      .reset_out        (glbl_rst_int)
   );

   assign glbl_rst_intn = !glbl_rst_int;
	
	//---------------
  // gtx_clk reset
   reset_sync gtx_reset_gen (
      .clk              (userclk2),
      .enable           (dcm_locked),
      .reset_in         (glbl_rst),
      .reset_out        (gtx_clk_reset_int)
   );

   // Create fully synchronous reset in the gtx_clk domain.
   always @(posedge userclk2)
   begin
     if (gtx_clk_reset_int) begin
       gtx_pre_resetn  <= 0;
       gtx_resetn      <= 0;
     end
     else begin
       gtx_pre_resetn  <= 1;
       gtx_resetn      <= gtx_pre_resetn;
     end
   end 

  //---------------
  // data check reset
   reset_sync chk_reset_gen (
      .clk              (userclk2),
      .enable           (dcm_locked),
      .reset_in         (glbl_rst || reset_error),
      .reset_out        (chk_reset_int)
   );

   // Create fully synchronous reset in the gtx_clk domain.
   always @(posedge userclk2)
   begin
     if (chk_reset_int) begin
       chk_pre_resetn  <= 0;
       chk_resetn      <= 0;
     end
     else begin
       chk_pre_resetn  <= 1;
       chk_resetn      <= chk_pre_resetn;
     end
   end 

   
   //---------------
   // PHY reset
   // the phy reset output (active low) needs to be held for at least 10x25MHZ cycles
   // this is derived using the 125MHz available and a 6 bit counter
   always @(posedge userclk2)
   begin
      if (!glbl_rst_intn) begin
         phy_resetn_int <= 0;
         phy_reset_count <= 0;
      end
      else begin
         if (!(&phy_reset_count)) begin
            phy_reset_count <= phy_reset_count + 1;
         end
         else begin
            phy_resetn_int <= 1;
         end
      end
   end
   
   assign phy_resetn = phy_resetn_int;
	
	// Clock circuitry for the Transceiver uses a differential input clock.
   // gtrefclk is routed to the tranceiver.
   IBUFDS_GTE2 ibufds_gtrefclk (
      .I     (gtrefclk_p),
      .IB    (gtrefclk_n),
      .CEB   (1'b0),
      .O     (gtrefclk),
      .ODIV2 ()
   );


   // Route txoutclk input through a BUFG
   BUFG  bufg_txoutclk (
      .I         (txoutclk),
      .O         (txoutclk_bufg)
   );
	 
	   // The GT transceiver provides a 62.5MHz clock to the FPGA fabrix.  This is 
  // routed to an MMCM module where it is used to create phase and frequency
  // related 62.5MHz and 125MHz clock sources
  MMCME2_ADV # (
    .BANDWIDTH            ("OPTIMIZED"),
    .CLKOUT4_CASCADE      ("FALSE"),
    .COMPENSATION         ("ZHOLD"),
    .STARTUP_WAIT         ("FALSE"),
    .DIVCLK_DIVIDE        (1),
    .CLKFBOUT_MULT_F      (10.000),
    .CLKFBOUT_PHASE       (0.000),
    .CLKFBOUT_USE_FINE_PS ("FALSE"),
    .CLKOUT0_DIVIDE_F     (10.000),
    .CLKOUT0_PHASE        (0.000),
    .CLKOUT0_DUTY_CYCLE   (0.5),
    .CLKOUT0_USE_FINE_PS  ("FALSE"),
    .CLKOUT1_DIVIDE       (5),
    .CLKOUT1_PHASE        (0.000),
    .CLKOUT1_DUTY_CYCLE   (0.5),
    .CLKOUT1_USE_FINE_PS  ("FALSE"),
    .CLKIN1_PERIOD        (16.0),
    .REF_JITTER1          (0.010)
  ) mmcm_adv_inst (
    // Output clocks
    .CLKFBOUT             (clkfbout),
    .CLKFBOUTB            (),
    .CLKOUT0              (clkout0),
    .CLKOUT0B             (),
    .CLKOUT1              (clkout1),
    .CLKOUT1B             (),
    .CLKOUT2              (),
    .CLKOUT2B             (),
    .CLKOUT3              (),
    .CLKOUT3B             (),
    .CLKOUT4              (),
    .CLKOUT5              (),
    .CLKOUT6              (),
    // Input clock control
    .CLKFBIN              (clkfbout),
    .CLKIN1               (txoutclk_bufg),
    .CLKIN2               (1'b0),
    // Tied to always select the primary input clock
    .CLKINSEL             (1'b1),
    // Ports for dynamic reconfiguration
    .DADDR                (7'h0),
    .DCLK                 (1'b0),
    .DEN                  (1'b0),
    .DI                   (16'h0),
    .DO                   (),
    .DRDY                 (),
    .DWE                  (1'b0),
    // Ports for dynamic phase shift
    .PSCLK                (1'b0),
    .PSEN                 (1'b0),
    .PSINCDEC             (1'b0),
    .PSDONE               (),
    // Other control and status signals
    .LOCKED               (dcm_locked),
    .CLKINSTOPPED         (),
    .CLKFBSTOPPED         (),
    .PWRDWN               (1'b0),
    .RST                  (mmcm_reset)
   );

    assign mmcm_reset = glbl_rst||!resetdone;

   // This 62.5MHz clock is placed onto global clock routing and is then used
   // for tranceiver TXUSRCLK/RXUSRCLK.
   BUFG bufg_userclk (
      .I     (clkout0),
      .O     (userclk)
   );


   // This 125MHz clock is placed onto global clock routing and is then used
   // to clock all Ethernet core logic.
   BUFG bufg_userclk2 (
      .I     (clkout1),
      .O     (userclk2)
   );
	 
	
	//---------------------------------------------------------------------------
   // Transceiver PMA reset circuitry
   //---------------------------------------------------------------------------

   always@(posedge clk_200_bufg or posedge glbl_rst)
      if (glbl_rst == 1'b1)
         pma_reset_pipe <= 4'b1111;
      else
         pma_reset_pipe <= {pma_reset_pipe[2:0], glbl_rst};

   assign pma_reset = pma_reset_pipe[3]; 
	 
	 //----------------------------------------------------------------------------
  // Instantiate the Core Block (core wrapper).
  //----------------------------------------------------------------------------
 gig_eth_pcs_pma_v11_2_block core_wrapper
     (
      .gtrefclk              (gtrefclk),
      .txp                   (txp),
      .txn                   (txn),
      .rxp                   (rxp),
      .rxn                   (rxn),
      .txoutclk              (txoutclk),
      .resetdone             (resetdone),
      .userclk               (userclk),
      .userclk2              (userclk2),
      .independent_clock_bufg(clk_200_bufg),
  //    .independent_clock_bufg(independent_clock_bufg),
      .pma_reset             (pma_reset),
      .sgmii_clk_r           (),
      .sgmii_clk_f           (),
   //   .sgmii_clk_r           (sgmii_clk_r),
   //   .sgmii_clk_f           (sgmii_clk_f),
      .sgmii_clk_en          (sgmii_clk_en),
      .gmii_txd              (gmii_txd),
      .gmii_tx_en            (gmii_tx_en),
      .gmii_tx_er            (gmii_tx_er),
      .gmii_rxd              (gmii_rxd),
      .gmii_rx_dv            (gmii_rx_dv),
      .gmii_rx_er            (gmii_rx_er),
      .gmii_isolate          (),
  //    .gmii_isolate          (gmii_isolate),
      .configuration_vector  (configuration_vector),
      .an_interrupt          (),
//     .an_interrupt          (an_interrupt),
      .an_adv_config_vector  (an_adv_config_vector),
      .an_restart_config     (an_restart_config),
      .link_timer_value      (link_timer_value),
      .speed_is_10_100       (speed_is_10_100),
      .speed_is_100          (speed_is_100),
      .status_vector         (status_vector_int),
      .reset                 (glbl_rst),       //(reset),
      .signal_detect          (signal_detect),
      .mmcm_locked             (dcm_locked)
      );
		
assign link_timer_value = 9'b000110010;
assign configuration_vector = 5'b10000;  //[4]AN enable,[3]Isolate disabled,[2]Powerdowndisabled,[1]loopback disabled, [0] Unidirectional disabled
assign signal_detect = 1'b1;
assign  an_adv_config_vector = 16'b0000000000100001;
assign  an_restart_config    = 1'b0;		
		
endmodule

6 Программное обеспечение

Программное обеспечение использует библиотеку WinPCAP для приема и передачи пакетов, передаваемых через интерфейс ethernet.

Все файлы проекта прикреплены к топику.
Файлы в топике: project.zip

Комментарии (9)

RSS свернуть / развернуть
Интересный пост, спасибо!
А еще интересней было бы разобраться с PCI-Express интерфейсом. Случайное не планируете?
0
Про реализацию на Xilinx непонятно, и совсем ничего не сказано про комповую часть. Также, если кто знает, подскажите платы с SGMII на этом чипе, аналогично модульку на DP83848 от waveshare.
0
платы на 88E1111
0
Не понятен вопрос. Что Вы имеете в виду? Марвелл Е1111 с ксилинксом вполне себе работают. Для примера digilent atlys или vc707 тот же
0
отдельный шилд с 88E1111 существует? очень хочется попробовать 1000M eth, но у моей платы (bemicro-cv) нет физики эзернетовской
0
Таких не встречал. Чтобы 1111 на шильдике. Требования к линиям суровые. На бордах среднего ценового сегмента -марвелл гигабитник обычное дело.
0
Добрый день, статья очень перспективная. Но на некоторых моментах я бы развернул бы. Для большей ясности. Поскольку шас все делают через трансиверы… но хотел бы прояснить FPGA — 88E11111 — RJ45 Причем тут magnetics? Завтра хочу открыть схему дэмо борда глянуть как сделано. Но на первый взгляд в топе у тебя не только ethernet задействован но и экран? Что то на экран ещё выводишь?
0
но хотел бы прояснить FPGA — 88E11111 — RJ45 Причем тут magnetics?
А что неясно? Развязывающе-согласующий трансформатор, обозначенный на блок-схеме как magnetics — необходимый элемент для эзернета.
0
Это я понял, когда открыл плату дэмо борда :)) Кстати а как быть если трансивер подключен через 1000Base-x?
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.