commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r10715 - in gnuradio/trunk/usrp2/fpga: . simple_gemac


From: matt
Subject: [Commit-gnuradio] r10715 - in gnuradio/trunk/usrp2/fpga: . simple_gemac
Date: Mon, 30 Mar 2009 16:52:00 -0600 (MDT)

Author: matt
Date: 2009-03-30 16:52:00 -0600 (Mon, 30 Mar 2009)
New Revision: 10715

Added:
   gnuradio/trunk/usrp2/fpga/simple_gemac/
   gnuradio/trunk/usrp2/fpga/simple_gemac/crc.v
   gnuradio/trunk/usrp2/fpga/simple_gemac/flow_ctrl_rx.v
   gnuradio/trunk/usrp2/fpga/simple_gemac/flow_ctrl_tx.v
   gnuradio/trunk/usrp2/fpga/simple_gemac/simple_gemac.v
   gnuradio/trunk/usrp2/fpga/simple_gemac/simple_gemac_tb.v
   gnuradio/trunk/usrp2/fpga/simple_gemac/simple_gemac_tx.v
Log:
work in progress on a simpler gigabit-only mac



Property changes on: gnuradio/trunk/usrp2/fpga/simple_gemac
___________________________________________________________________
Added: svn:ignore
   + a.out
*~
*.vcd


Added: gnuradio/trunk/usrp2/fpga/simple_gemac/crc.v
===================================================================
--- gnuradio/trunk/usrp2/fpga/simple_gemac/crc.v                                
(rev 0)
+++ gnuradio/trunk/usrp2/fpga/simple_gemac/crc.v        2009-03-30 22:52:00 UTC 
(rev 10715)
@@ -0,0 +1,63 @@
+
+module crc
+  (input clk, 
+   input reset,
+   input clear, 
+   input [7:0] data,
+   input calc,
+   output [31:0] crc_out);
+   
+   function[31:0]  NextCRC;
+      input[7:0]      D;
+      input[31:0]     C;
+      reg[31:0]       NewCRC;
+      begin
+        NewCRC[0]   = C[24]^C[30]^D[1]^D[7];
+        NewCRC[1]   = C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7];
+        NewCRC[2]   = C[26]^D[5]^C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7];
+        NewCRC[3]   = C[27]^D[4]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6];
+        NewCRC[4]   = C[28]^D[3]^C[27]^D[4]^C[26]^D[5]^C[24]^C[30]^D[1]^D[7];
+        NewCRC[5]   = 
C[29]^D[2]^C[28]^D[3]^C[27]^D[4]^C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7];
+        NewCRC[6]   = 
C[30]^D[1]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6];
+        NewCRC[7]   = C[31]^D[0]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[24]^D[7];
+        NewCRC[8]   = C[0]^C[28]^D[3]^C[27]^D[4]^C[25]^D[6]^C[24]^D[7];
+        NewCRC[9]   = C[1]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^D[6];
+        NewCRC[10]  = C[2]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[24]^D[7];
+        NewCRC[11]  = C[3]^C[28]^D[3]^C[27]^D[4]^C[25]^D[6]^C[24]^D[7];
+        NewCRC[12]  = 
C[4]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^D[6]^C[24]^C[30]^D[1]^D[7];
+        NewCRC[13]  = 
C[5]^C[30]^D[1]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6];
+        NewCRC[14]  = 
C[6]^C[31]^D[0]^C[30]^D[1]^C[28]^D[3]^C[27]^D[4]^C[26]^D[5];
+        NewCRC[15]  = C[7]^C[31]^D[0]^C[29]^D[2]^C[28]^D[3]^C[27]^D[4];
+        NewCRC[16]  = C[8]^C[29]^D[2]^C[28]^D[3]^C[24]^D[7];
+        NewCRC[17]  = C[9]^C[30]^D[1]^C[29]^D[2]^C[25]^D[6];
+        NewCRC[18]  = C[10]^C[31]^D[0]^C[30]^D[1]^C[26]^D[5];
+        NewCRC[19]  = C[11]^C[31]^D[0]^C[27]^D[4];
+        NewCRC[20]  = C[12]^C[28]^D[3];
+        NewCRC[21]  = C[13]^C[29]^D[2];
+        NewCRC[22]  = C[14]^C[24]^D[7];
+        NewCRC[23]  = C[15]^C[25]^D[6]^C[24]^C[30]^D[1]^D[7];
+        NewCRC[24]  = C[16]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6];
+        NewCRC[25]  = C[17]^C[27]^D[4]^C[26]^D[5];
+        NewCRC[26]  = C[18]^C[28]^D[3]^C[27]^D[4]^C[24]^C[30]^D[1]^D[7];
+        NewCRC[27]  = C[19]^C[29]^D[2]^C[28]^D[3]^C[25]^C[31]^D[0]^D[6];
+        NewCRC[28]  = C[20]^C[30]^D[1]^C[29]^D[2]^C[26]^D[5];
+        NewCRC[29]  = C[21]^C[31]^D[0]^C[30]^D[1]^C[27]^D[4];
+        NewCRC[30]  = C[22]^C[31]^D[0]^C[28]^D[3];
+        NewCRC[31]  = C[23]^C[29]^D[2];
+        NextCRC     = NewCRC;
+      end
+   endfunction
+
+   reg [31:0] crc_reg;
+   always @ (posedge clk)
+     if (reset | clear)
+       crc_reg             <= 32'hffffffff;
+     else if (calc)
+       crc_reg             <= NextCRC(data,crc_reg);
+        
+   assign crc_out    = 
~{crc_reg[24],crc_reg[25],crc_reg[26],crc_reg[27],crc_reg[28],crc_reg[29],crc_reg[30],crc_reg[31],
+                     
crc_reg[16],crc_reg[17],crc_reg[18],crc_reg[19],crc_reg[20],crc_reg[21],crc_reg[22],crc_reg[23],
+                     
crc_reg[8],crc_reg[9],crc_reg[10],crc_reg[11],crc_reg[12],crc_reg[13],crc_reg[14],crc_reg[15],
+                     
crc_reg[0],crc_reg[1],crc_reg[2],crc_reg[3],crc_reg[4],crc_reg[5],crc_reg[6],crc_reg[7]
 };
+   
+endmodule // crc

Added: gnuradio/trunk/usrp2/fpga/simple_gemac/flow_ctrl_rx.v
===================================================================
--- gnuradio/trunk/usrp2/fpga/simple_gemac/flow_ctrl_rx.v                       
        (rev 0)
+++ gnuradio/trunk/usrp2/fpga/simple_gemac/flow_ctrl_rx.v       2009-03-30 
22:52:00 UTC (rev 10715)
@@ -0,0 +1,85 @@
+
+// RX side of flow control -- when we are running out of RX space, send a PAUSE
+
+module flow_ctrl_rx
+  (input        rst,
+   //host processor
+   input        pause_frame_send_en,
+   input [15:0] pause_quanta_set,
+   input [15:0] fc_hwmark,
+   input [15:0] fc_lwmark,
+   // From MAC_rx_ctrl
+   input        rx_clk,
+   input [15:0] rx_fifo_space,
+   // MAC_tx_ctrl
+   input        tx_clk,
+   output reg   xoff_gen,
+   output reg   xon_gen,
+   input        xoff_gen_complete,
+   input        xon_gen_complete
+   );
+   
+   // 
******************************************************************************  
      
+   // Force our TX to send a PAUSE frame because our RX is nearly full
+   // 
******************************************************************************
+
+   reg xon_int, xoff_int;
+   reg [21:0] countdown;
+ 
+   always @(posedge rx_clk or posedge rst)
+     if(rst)
+       begin
+         xon_int <= 0;
+         xoff_int <= 0;
+       end
+     else 
+       begin
+         xon_int <= 0;
+         xoff_int <= 0;
+         if(pause_frame_send_en)
+           if(countdown == 0)
+             if(rx_fifo_space < fc_lwmark)
+               xoff_int <= 1;
+             else
+               ;
+           else
+             if(rx_fifo_space > fc_hwmark)
+               xon_int <= 1;
+       end // else: !if(rst)
+   
+   reg xoff_int_d1, xon_int_d1;
+
+   always @(posedge rx_clk)
+     xon_int_d1 <= xon_int;
+   always @(posedge rx_clk)
+     xoff_int_d1 <= xoff_int;
+   
+   always @ (posedge tx_clk or posedge rst)
+     if (rst)
+       xoff_gen        <=0;
+     else if (xoff_gen_complete)
+       xoff_gen        <=0;
+     else if (xoff_int | xoff_int_d1)
+       xoff_gen        <=1;
+   
+   always @ (posedge tx_clk or posedge rst)
+     if (rst)
+       xon_gen     <=0;
+     else if (xon_gen_complete)
+       xon_gen     <=0;
+     else if (xon_int | xon_int_d1)
+       xon_gen     <=1;                     
+
+   wire [15:0] pq_reduced = pause_quanta_set - 2;
+   
+   always @(posedge tx_clk or posedge rst)
+     if(rst)
+       countdown <= 0;
+     else if(xoff_gen)
+       countdown <= {pq_reduced,6'd0};
+     else if(xon_gen)
+       countdown <= 0;
+     else if(countdown != 0)
+       countdown <= countdown - 1;
+   
+endmodule // flow_ctrl

Added: gnuradio/trunk/usrp2/fpga/simple_gemac/flow_ctrl_tx.v
===================================================================
--- gnuradio/trunk/usrp2/fpga/simple_gemac/flow_ctrl_tx.v                       
        (rev 0)
+++ gnuradio/trunk/usrp2/fpga/simple_gemac/flow_ctrl_tx.v       2009-03-30 
22:52:00 UTC (rev 10715)
@@ -0,0 +1,36 @@
+
+// TX side of flow control -- when other side sends PAUSE, we wait
+
+module flow_ctrl_tx
+  (input        rst,
+   input        tx_clk,
+   //host processor
+   input        tx_pause_en,
+   // From MAC_rx_ctrl
+   input [15:0] pause_quanta,
+   input        pause_quanta_val,
+   // MAC_tx_ctrl
+   output       pause_apply,
+   input        pause_quanta_sub);
+     
+   // 
******************************************************************************  
      
+   // Inhibit our TX from transmitting because they sent us a PAUSE frame
+   // 
******************************************************************************
+
+   reg [15:0]  pause_quanta_counter;
+   reg                 pqval_d1, pqval_d2;             
+
+   always @(posedge tx_clk) pqval_d1 <= pause_quanta_val;
+   always @(posedge tx_clk) pqval_d2 <= pqval_d1;
+
+   always @ (posedge tx_clk or posedge rst)
+     if (rst)
+       pause_quanta_counter <= 0;
+     else if (pqval_d1 & ~pqval_d2)
+       pause_quanta_counter <= pause_quanta; 
+     else if((pause_quanta_counter!=0) & pause_quanta_sub)
+       pause_quanta_counter <= pause_quanta_counter - 1;
+
+   assign      pause_apply = tx_pause_en & (pause_quanta_counter != 0);
+   
+endmodule // flow_ctrl

Added: gnuradio/trunk/usrp2/fpga/simple_gemac/simple_gemac.v
===================================================================
--- gnuradio/trunk/usrp2/fpga/simple_gemac/simple_gemac.v                       
        (rev 0)
+++ gnuradio/trunk/usrp2/fpga/simple_gemac/simple_gemac.v       2009-03-30 
22:52:00 UTC (rev 10715)
@@ -0,0 +1,55 @@
+
+module simple_gemac
+  (input clk125, input reset,
+   // GMII
+   output GMII_GTX_CLK, output GMII_TX_EN, output GMII_TX_ER, output [7:0] 
GMII_TXD,
+   input GMII_RX_CLK, input GMII_RX_DV, input GMII_RX_ER, input [7:0] GMII_RXD,
+
+   // Flow Control Interface
+   input pause_req, input [15:0] pause_time,
+
+   // RX Client Interface
+   output rx_clk, output [7:0] rx_data, output rx_valid, output rx_error, 
output rx_ack,
+
+   // TX Client Interface
+   output tx_clk, input [7:0] tx_data, input tx_valid, input tx_error, output 
tx_ack
+   );
+
+   localparam SGE_IFG               = 8'd12;  // 12 should be the absolute 
minimum
+   localparam SGE_RESPECT_FLOW_CTRL  = 1'b1;  // stop sending if other side 
requests
+
+   wire rst_rxclk, rst_txclk;   
+   oneshot_2clk tx_rst_1shot 
(.clk_in(tx_clk),.in(reset),.clk_out(tx_clk),.out(rst_txclk));  // FIXME clocks
+   oneshot_2clk rx_rst_1shot 
(.clk_in(sys_clk),.in(reset),.clk_out(rx_clk),.out(rst_rxclk));
+
+   wire [15:0] pause_quanta_rcvd;
+   
+   simple_gemac_tx simple_gemac_tx
+     (.clk125(clk125),.reset(rst_txclk),
+      .GMII_GTX_CLK(GMII_GTX_CLK), .GMII_TX_EN(GMII_TX_EN),
+      .GMII_TX_ER(GMII_TX_ER), .GMII_TXD(GMII_TXD),
+      .tx_clk(tx_clk), .tx_data(tx_data), .tx_valid(tx_valid), 
.tx_error(tx_error), .tx_ack(tx_ack),
+      .ifg(SGE_IFG), .mac_addr(48'hF1_F2_F3_F4_F5_F6),
+      .pause_req(pause_req), .pause_time(pause_time),  // We request flow 
control
+      .pause_apply(pause_apply), .pause_applied(pause_applied)  // We respect 
flow control
+      );
+/*
+   simple_gemac_rx simple_gemac_rx
+     (.reset(rst_rxclk),
+      .GMII_RX_CLK(GMII_RX_CLK), .GMII_RX_DV(GMII_RX_DV), 
+      .GMII_RX_ER(GMII_RX_ER), .GMII_RXD(GMII_RXD),
+      .rx_clk(rx_clk), .rx_data(rx_data), .rx_valid(rx_valid), 
.rx_error(rx_error), .rx_ack(rx_ack),
+      .pause_quanta_rcvd(pause_qanta_rcvd), .pause_rcvd(pause_rcvd) 
+      );
+  */ 
+   flow_ctrl_tx flow_ctrl_tx
+     (.rst(reset_txclk), .tx_clk(tx_clk),
+      .tx_pause_en(SGE_RESPECT_FLOW_CTRL),
+      .pause_quanta(pause_quanta_rcvd), // 16 bit value
+      .pause_quanta_val(pause_rcvd),
+      .pause_apply(pause_apply),
+      .pause_quanta_sub(pause_applied)
+      );
+
+   
+endmodule // simple_gemac

Added: gnuradio/trunk/usrp2/fpga/simple_gemac/simple_gemac_tb.v
===================================================================
--- gnuradio/trunk/usrp2/fpga/simple_gemac/simple_gemac_tb.v                    
        (rev 0)
+++ gnuradio/trunk/usrp2/fpga/simple_gemac/simple_gemac_tb.v    2009-03-30 
22:52:00 UTC (rev 10715)
@@ -0,0 +1,88 @@
+
+
+module simple_gemac_tb;
+
+     
+   reg clk = 0;
+   reg reset = 1;
+
+   initial #1000 reset = 0;
+   always #50 clk = ~clk;
+
+   wire GMII_RX_DV, GMII_RX_ER, GMII_TX_EN, GMII_TX_ER;
+   wire [7:0] GMII_RXD, GMII_TXD;
+
+   wire rx_valid, rx_error, rx_ack;
+   wire tx_ack;
+   reg tx_valid = 0, tx_error = 0;
+   
+   wire [7:0] rx_data;
+   reg [7:0] tx_data;
+   
+   wire [15:0] pause_time = 16'hBEEF;
+   reg pause_req = 0;
+   
+   simple_gemac simple_gemac
+     (.clk125(clk),  .reset(reset),
+      .GMII_GTX_CLK(GMII_GTX_CLK), .GMII_TX_EN(GMII_TX_EN),  
+      .GMII_TX_ER(GMII_TX_ER), .GMII_TXD(GMII_TXD),
+      .GMII_RX_CLK(GMII_RX_CLK), .GMII_RX_DV(GMII_RX_DV),  
+      .GMII_RX_ER(GMII_RX_ER), .GMII_RXD(GMII_RXD),
+      .pause_req(pause_req), .pause_time(pause_time),
+      .rx_clk(rx_clk), .rx_data(rx_data),
+      .rx_valid(rx_valid), .rx_error(rx_error), .rx_ack(rx_ack),
+      .tx_clk(tx_clk), .tx_data(tx_data), 
+      .tx_valid(tx_valid), .tx_error(tx_error), .tx_ack(tx_ack)
+      );
+
+   task SendFlowCtrl;
+     begin
+       $display("Sending Flow Control");
+       @(posedge clk);
+       pause_req <= 1;
+       @(posedge clk);
+       pause_req <= 0;
+     end
+   endtask // SendFlowCtrl
+
+   reg [31:0] count;
+   task SendPacket;
+      input [7:0] data_start;
+      input [31:0] data_len;
+      begin
+        $display("Sending Packet");
+        count <= 0;
+        tx_data  <= data_start;
+        tx_error <= 0;
+        tx_valid <= 1;
+        while(~tx_ack)
+          @(posedge tx_clk);
+        while(count < data_len)
+          begin
+             tx_data <= tx_data + 1;
+             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);
+       
+   initial
+     begin
+       @(negedge reset);
+       repeat (20)
+         @(posedge clk);
+       SendFlowCtrl;
+       repeat (100)
+         @(posedge clk);
+       SendPacket(8'hAA,10);
+       repeat (1000)
+         @(posedge clk);
+       $finish;
+     end
+   
+endmodule // simple_gemac_tb

Added: gnuradio/trunk/usrp2/fpga/simple_gemac/simple_gemac_tx.v
===================================================================
--- gnuradio/trunk/usrp2/fpga/simple_gemac/simple_gemac_tx.v                    
        (rev 0)
+++ gnuradio/trunk/usrp2/fpga/simple_gemac/simple_gemac_tx.v    2009-03-30 
22:52:00 UTC (rev 10715)
@@ -0,0 +1,200 @@
+
+module simple_gemac_tx
+  (input clk125, input reset,
+   output GMII_GTX_CLK, output reg GMII_TX_EN, output reg GMII_TX_ER, output 
reg [7:0] GMII_TXD,
+   output tx_clk, input [7:0] tx_data, input tx_valid, input tx_error, output 
tx_ack,
+   input [7:0] ifg, input [47:0] mac_addr,
+   input pause_req, input [15:0] pause_time,
+   input pause_apply, output pause_applied
+   );
+   
+   assign GMII_GTX_CLK  = clk125;
+   assign tx_clk       = clk125;
+   
+   reg [7:0] tx_state;
+   reg [7:0] ifg_ctr;
+   reg [15:0] frame_len_ctr;
+   reg [7:0] pause_ctr, pause_dat;
+
+   wire in_ifg                      = (ifg_ctr != 0);
+
+   wire [31:0] crc_out;
+   
+   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))
+       frame_len_ctr       <= 0;
+     else
+       frame_len_ctr       <= frame_len_ctr + 1;
+   
+   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_IN_FRAME_2  = TX_IN_FRAME + 1;
+   localparam TX_PAD        = TX_IN_FRAME_2 + 1;
+   localparam TX_CRC_0              = 16;
+   localparam TX_CRC_1              = TX_CRC_0 + 1;
+   localparam TX_CRC_2              = TX_CRC_0 + 2;
+   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_END   = TX_PAUSE_SOF + 18;
+
+   reg send_pause;
+   reg [15:0] pause_time_held;
+   
+   always @(posedge tx_clk)
+     if(reset)
+       send_pause      <= 0;
+     else if(pause_req)
+       send_pause      <= 1;
+     else if(tx_state == TX_PAUSE)
+       send_pause      <= 0;
+
+   always @(posedge tx_clk)
+     if(pause_req)
+       pause_time_held <= pause_time;
+   
+   always @(posedge tx_clk)
+     if(reset)
+       tx_state        <= TX_IDLE;
+     else 
+       case(tx_state)
+        TX_IDLE :
+          if(~in_ifg)
+            if(send_pause)
+              tx_state <= TX_PAUSE;
+            else if(tx_valid)
+              tx_state <= TX_PREAMBLE;
+        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)
+            tx_state <= TX_IN_FRAME_2;
+        TX_IN_FRAME_2 :
+          if(tx_error)
+            tx_state <= TX_ERROR;   // underrun
+          else if(~tx_valid)
+            tx_state <= TX_CRC_0;
+        TX_PAD :
+          if(frame_len_ctr == MIN_FRAME_LEN)
+            tx_state <= TX_CRC_0;
+        TX_CRC_3 :
+          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;
+       endcase // case (tx_state)
+
+   always @(posedge tx_clk)
+     if(reset)
+       begin
+         GMII_TX_EN <= 0;
+         GMII_TX_ER <= 0;
+         GMII_TXD   <= 0;
+       end
+     else
+       casex(tx_state)
+        TX_IDLE :
+          begin
+             GMII_TX_EN <= 0;
+             GMII_TX_ER <= 0;
+             GMII_TXD <= 0;
+          end
+        TX_PREAMBLE, TX_PAUSE_PRE :
+          begin
+             GMII_TXD   <= 8'h55;
+             GMII_TX_EN <= 1;
+          end
+        TX_SOF_DEL, TX_PAUSE_SOF :
+          GMII_TXD <= 8'hD5;
+        TX_IN_FRAME, TX_IN_FRAME_2 :
+          GMII_TXD <= tx_data;
+        TX_ERROR :
+          begin
+             GMII_TX_ER <= 1;
+             GMII_TXD   <= 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_PAD :
+          GMII_TXD <= 0;
+        8'b01xx_xxxx :  // In Pause Frame
+          GMII_TXD <= pause_dat;
+       endcase // case (tx_state)
+
+   localparam SGE_FLOW_CTRL_ADDR  = 48'h01_80_C2_00_00_01;
+   always @(posedge tx_clk)
+     case(tx_state)
+       TX_PAUSE_SOF :
+        pause_dat    <= SGE_FLOW_CTRL_ADDR[47:40];  // Note everything must be 
1 cycle early
+       TX_PAUSE_SOF + 1:
+        pause_dat    <= SGE_FLOW_CTRL_ADDR[39:32];
+       TX_PAUSE_SOF + 2:
+        pause_dat    <= SGE_FLOW_CTRL_ADDR[31:24];
+       TX_PAUSE_SOF + 3:
+        pause_dat    <= SGE_FLOW_CTRL_ADDR[23:16];
+       TX_PAUSE_SOF + 4:
+        pause_dat    <= SGE_FLOW_CTRL_ADDR[15:8];
+       TX_PAUSE_SOF + 5:
+        pause_dat    <= SGE_FLOW_CTRL_ADDR[7:0];
+       TX_PAUSE_SOF + 6:
+        pause_dat    <= mac_addr[47:40];
+       TX_PAUSE_SOF + 7:
+        pause_dat    <= mac_addr[39:32];
+       TX_PAUSE_SOF + 8:
+        pause_dat    <= mac_addr[31:24];
+       TX_PAUSE_SOF + 9:
+        pause_dat    <= mac_addr[23:16];
+       TX_PAUSE_SOF + 10:
+        pause_dat    <= mac_addr[15:8];
+       TX_PAUSE_SOF + 11:
+        pause_dat <= mac_addr[7:0];
+       TX_PAUSE_SOF + 12:
+        pause_dat <= 8'h88;   // Type = 8808 = MAC ctrl frame
+       TX_PAUSE_SOF + 13:
+        pause_dat <= 8'h08;
+       TX_PAUSE_SOF + 14:
+        pause_dat <= 8'h00;   // Opcode = 0001 = PAUSE
+       TX_PAUSE_SOF + 15:
+        pause_dat <= 8'h01;
+       TX_PAUSE_SOF + 16:
+        pause_dat <= pause_time_held[15:8];
+       TX_PAUSE_SOF + 17:
+        pause_dat <= pause_time_held[7:0];
+     endcase // case (tx_state)
+   
+   wire start_ifg   = (tx_state == TX_CRC_3);
+   always @(posedge tx_clk)
+     if(reset)
+       ifg_ctr            <= 100;
+     else if(start_ifg)
+       ifg_ctr            <= ifg;
+     else if(ifg_ctr != 0)
+       ifg_ctr            <= ifg_ctr - 1;
+
+   wire clear_crc   = (tx_state == TX_IDLE);
+   wire calc_crc    = 1;
+   
+   crc crc(.clk(tx_clk), .reset(reset), .clear(clear_crc),
+           .data(GMII_TXD), .calc(calc_crc), .crc_out(crc_out));
+
+   assign tx_ack = (tx_state == TX_IN_FRAME);
+endmodule // simple_gemac_tx





reply via email to

[Prev in Thread] Current Thread [Next in Thread]