diff options
| -rw-r--r-- | simple_gemac/simple_gemac_tb.v | 68 | ||||
| -rw-r--r-- | simple_gemac/simple_gemac_tx.v | 108 | 
2 files changed, 134 insertions, 42 deletions
| diff --git a/simple_gemac/simple_gemac_tb.v b/simple_gemac/simple_gemac_tb.v index 61dbbe4c9..30a475960 100644 --- a/simple_gemac/simple_gemac_tb.v +++ b/simple_gemac/simple_gemac_tb.v @@ -38,6 +38,7 @@ module simple_gemac_tb;     task SendFlowCtrl;       begin  	$display("Sending Flow Control"); +	 $display($time);  	@(posedge clk);  	pause_req <= 1;  	@(posedge clk); @@ -51,12 +52,15 @@ module simple_gemac_tb;        input [31:0] data_len;        begin  	 $display("Sending Packet"); +	 $display($time);  	 count <= 0;  	 tx_data  <= data_start;  	 tx_error <= 0;  	 tx_valid <= 1;  	 while(~tx_ack)  	   @(posedge tx_clk); +	 $display("Packet Accepted"); +	 $display($time);  	 while(count < data_len)  	   begin  	      tx_data <= tx_data + 1; @@ -68,21 +72,75 @@ module simple_gemac_tb;        end     endtask // SendPacket +   task SendPacketFromFile; +      input [31:0] data_len; +      begin +	 $display("Sending Packet From File"); +	 $display($time); +	 $readmemh( "test_packet.mem",pkt_rom );      +	 count 	  = 0; +	 tx_data  = pkt_rom[count]; +	 tx_error = 0; +	 tx_valid = 1; +	 while(~tx_ack) +	   @(posedge tx_clk); +	 $display("Packet Accepted"); +	 $display($time); +	 count = 1; +	 while(count < data_len) +	   begin +	      tx_data = pkt_rom[count]; +	      count   = count + 1; +	      @(posedge clk); +	   end +	 tx_valid <= 0; +	 @(posedge tx_clk); +      end +   endtask // SendPacket +   	     initial $dumpfile("simple_gemac_tb.vcd");     initial $dumpvars(0,simple_gemac_tb); -	 + +   integer i;  +   reg [7:0] pkt_rom[0:65535]; +   reg [1023:0] ROMFile; +    +   initial +     for (i=0;i<65536;i=i+1) +       pkt_rom[i] <= 8'h0; +           initial       begin  	@(negedge reset);  	repeat (20)  	  @(posedge clk);  	SendFlowCtrl; -	repeat (100) +	//repeat (200)  	  @(posedge clk);  	SendPacket(8'hAA,10); -	repeat (1000) -	  @(posedge clk); -	$finish; +	//repeat (100) +	//  @(posedge clk); +	SendPacketFromFile(60); +	SendPacketFromFile(59); +	SendPacketFromFile(58); +	#10000 $finish;       end + +   always @(posedge clk) +     if(GMII_TX_EN) +       $display("%x",GMII_TXD);  endmodule // simple_gemac_tb + +/* +    if ( !$value$plusargs( "rom=%s", ROMFile ) ) +        begin +           $display( "Using default ROM file, 'flash.rom'" ); +           ROMFile = "flash.rom"; +        end +      else +	$display( "Using %s as ROM file.", ROMFile); +       +      #1 $readmemh( ROMFile,rom );      +   end + */ diff --git a/simple_gemac/simple_gemac_tx.v b/simple_gemac/simple_gemac_tx.v index cddb18a3a..b104d91a5 100644 --- a/simple_gemac/simple_gemac_tx.v +++ b/simple_gemac/simple_gemac_tx.v @@ -7,9 +7,12 @@ module simple_gemac_tx     input pause_req, input [15:0] pause_time,     input pause_apply, output pause_applied     ); + +   reg tx_en_pre, tx_er_pre; +   reg [7:0] txd_pre; -   assign GMII_GTX_CLK  = clk125; -   assign tx_clk       = clk125; +   assign GMII_GTX_CLK 	= clk125; +   assign tx_clk 	= clk125;     reg [7:0] tx_state;     reg [7:0] ifg_ctr; @@ -23,7 +26,7 @@ module simple_gemac_tx     localparam MIN_FRAME_LEN  = 64 + 8 - 4; // Min frame length includes preamble but not CRC     localparam MAX_FRAME_LEN  = 8192;       // How big are the jumbo frames we want to handle?     always @(posedge tx_clk) -     if(reset |(tx_state <= TX_IDLE)) +     if(reset |(tx_state == TX_IDLE))         frame_len_ctr 	    <= 0;       else         frame_len_ctr 	    <= frame_len_ctr + 1; @@ -31,7 +34,8 @@ module simple_gemac_tx     localparam TX_IDLE 	     = 0;     localparam TX_PREAMBLE    = 1;     localparam TX_SOF_DEL     = TX_PREAMBLE + 7; -   localparam TX_IN_FRAME    = TX_SOF_DEL + 1; +   localparam TX_FIRSTBYTE   = TX_SOF_DEL + 1; +   localparam TX_IN_FRAME    = TX_FIRSTBYTE + 1;     localparam TX_IN_FRAME_2  = TX_IN_FRAME + 1;     localparam TX_PAD 	     = TX_IN_FRAME_2 + 1;     localparam TX_CRC_0 	     = 16; @@ -40,13 +44,12 @@ module simple_gemac_tx     localparam TX_CRC_3 	     = TX_CRC_0 + 3;     localparam TX_ERROR 	     = 32;     localparam TX_PAUSE 	     = 56; -   localparam TX_PAUSE_PRE   = TX_PAUSE + 1; -   localparam TX_PAUSE_SOF   = 64; +   localparam TX_PAUSE_SOF   = 63;     localparam TX_PAUSE_END   = TX_PAUSE_SOF + 18;     reg send_pause;     reg [15:0] pause_time_held; -    +     always @(posedge tx_clk)       if(reset)         send_pause      <= 0; @@ -70,12 +73,19 @@ module simple_gemac_tx  	       tx_state <= TX_PAUSE;  	     else if(tx_valid)  	       tx_state <= TX_PREAMBLE; +	 TX_FIRSTBYTE : +	   if(tx_error) +	     tx_state <= TX_ERROR;   // underrun +	   else if(~tx_valid) +	     tx_state <= TX_PAD; +	   else +	     tx_state <= TX_IN_FRAME;  	 TX_IN_FRAME :  	   if(tx_error)  	     tx_state <= TX_ERROR;   // underrun  	   else if(~tx_valid)  	     tx_state <= TX_PAD; -	   else if(frame_len_ctr == MIN_FRAME_LEN) +	   else if(frame_len_ctr == MIN_FRAME_LEN - 1)  	     tx_state <= TX_IN_FRAME_2;  	 TX_IN_FRAME_2 :  	   if(tx_error) @@ -89,55 +99,48 @@ module simple_gemac_tx  	   tx_state <= TX_IDLE;  	 TX_ERROR :  	   tx_state <= TX_IDLE; -	 TX_PAUSE : -	   tx_state <= TX_PAUSE_PRE;  	 TX_PAUSE_END :  	   tx_state <= TX_PAD;  	 default : -	   tx_state  <= tx_state + 1; +	   tx_state <= tx_state + 1;         endcase // case (tx_state)     always @(posedge tx_clk)       if(reset)         begin -	  GMII_TX_EN <= 0; -	  GMII_TX_ER <= 0; -	  GMII_TXD   <= 0; +	  tx_en_pre <= 0; +	  tx_er_pre <= 0; +	  txd_pre   <= 0;         end       else         casex(tx_state)  	 TX_IDLE :  	   begin -	      GMII_TX_EN <= 0; -	      GMII_TX_ER <= 0; -	      GMII_TXD <= 0; +	      tx_en_pre <= 0; +	      tx_er_pre <= 0; +	      txd_pre <= 0;  	   end -	 TX_PREAMBLE, TX_PAUSE_PRE : +	 TX_PREAMBLE, TX_PAUSE :  	   begin -	      GMII_TXD 	 <= 8'h55; -	      GMII_TX_EN <= 1; +	      txd_pre 	 <= 8'h55; +	      tx_en_pre <= 1;  	   end  	 TX_SOF_DEL, TX_PAUSE_SOF : -	   GMII_TXD <= 8'hD5; -	 TX_IN_FRAME, TX_IN_FRAME_2 : -	   GMII_TXD <= tx_data; +	   txd_pre <= 8'hD5; +	 TX_FIRSTBYTE, TX_IN_FRAME, TX_IN_FRAME_2 : +	   txd_pre <= tx_valid ? tx_data : 0;  	 TX_ERROR :  	   begin -	      GMII_TX_ER <= 1; -	      GMII_TXD 	 <= 0; +	      tx_er_pre <= 1; +	      txd_pre 	 <= 0;  	   end -	 TX_CRC_0 : -	   GMII_TXD <= crc_out[31:24]; -	 TX_CRC_1 : -	   GMII_TXD <= crc_out[23:16]; -	 TX_CRC_2 : -	   GMII_TXD <= crc_out[15:8];  	 TX_CRC_3 : -	   GMII_TXD <= crc_out[7:0]; +	   tx_en_pre <= 0;  	 TX_PAD : -	   GMII_TXD <= 0; +	   txd_pre <= 0; +   	 8'b01xx_xxxx :  // In Pause Frame -	   GMII_TXD <= pause_dat; +	   txd_pre <= pause_dat;         endcase // case (tx_state)     localparam SGE_FLOW_CTRL_ADDR  = 48'h01_80_C2_00_00_01; @@ -191,10 +194,41 @@ module simple_gemac_tx         ifg_ctr 	   <= ifg_ctr - 1;     wire clear_crc   = (tx_state == TX_IDLE); -   wire calc_crc    = 1; + +   wire calc_crc_pre = (tx_state==TX_FIRSTBYTE)||(tx_state==TX_IN_FRAME)|| +	((tx_state==TX_IN_FRAME_2)&tx_valid )||(tx_state==TX_PAD )||(tx_state[6]); +   reg calc_crc; +   always @(posedge tx_clk) +     calc_crc <= calc_crc_pre;     crc crc(.clk(tx_clk), .reset(reset), .clear(clear_crc), -	    .data(GMII_TXD), .calc(calc_crc), .crc_out(crc_out)); +	    .data(txd_pre), .calc(calc_crc), .crc_out(crc_out)); + +   assign tx_ack    = (tx_state == TX_FIRSTBYTE); -   assign tx_ack = (tx_state == TX_IN_FRAME); +   reg tx_valid_d1; +   always @(posedge tx_clk) +     tx_valid_d1   <= tx_valid; +    +   always @(posedge tx_clk)  +     begin +	GMII_TX_EN <= tx_en_pre; +	GMII_TX_ER <= tx_er_pre; +	case(tx_state) +	  TX_CRC_0 : +	    GMII_TXD <= crc_out[31:24]; +	  TX_CRC_1 : +	    GMII_TXD <= crc_out[23:16]; +	  TX_CRC_2 : +	    GMII_TXD <= crc_out[15:8]; +	  TX_CRC_3 : +	    GMII_TXD <= crc_out[7:0]; +//	  TX_IN_FRAME :  +//	  TX_PAD : +//	    GMII_TXD <= tx_valid_d1 ? txd_pre : 0; +	  default : +	    GMII_TXD <= txd_pre; +	endcase // case (tx_state) +     end +     endmodule // simple_gemac_tx | 
