Commits

Christopher Felton committed daf292b

simulation and emulation of the simple_gemac_core

  • Participants
  • Parent commits d52c773

Comments (0)

Files changed (22)

2014/examples/simple_gemac_core/NOTES.md

+
+
+The common top-level is the simple_gemac_wrapper.v (odd name), this 
+include a MM bus and FIFO chains.
+
+## FIFOs
+The original implemenation contained Xilinx specific FIFOs, this 
+implemenation replaces the Xilinx FIFOs with generic FIFOs.  These
+FIFOs are implemented in MyHDL, they are converted for a specific 
+type (size, width, etc.).  If used in a MyHDL design not the case.
+
+### TX FIFO chain
+
+    The following is the TX FIFO chain, don't understand the logic
+    between the 3 (2 types) FIFOs, why not just one larger FIFO.
+    Doesn't look like the widths are separate sizes.  It must be a 
+    speed thing.
+
+    simple_gemac_wrapper:
+      fifo_2clock_cascade (u_tx_2clk_fifo) : 
+                           (WIDTH=36, SIZE=6)
+                           16-word FIFO -> 512 word FIFO -> 16 word FIFO
+      
+          fifo_short  : (WIDTH=36, DEPTH=16) depth is fixed to 16
+      	              this fifo explicitly uses SRL16E, this can be
+                        replaced by a simple FIFO, synthesis should take
+      		      care of this.  Future enhancement can have option
+      		      to select target optimizations.
+      		      
+      		      width is set to 36 (input and output) at top
+      
+      	fifo_2clock : 
+      
+      	fifo_short  : 
+      
+        --> .datain(tx_f36_data)
+	<-- .dataout(tx_f36_data_int1)
+
+      fifo36_toll8 : convert 36-bit word, f36_data to four 8-bit outputs
+
+        --> .f36_data(tx_f36_data_int1),
+	<-- .ll_data(tx_ll_data2)
+
+### RX FIFO chain
+    
+    The RX FIFO chain starts at the simple_gemac *rx_data*
+
+    simple_gemac
+      rxmac_to_ll8
+      ll8_shortfifo
+      ll8_to_fifo36
+      m_fifo_2clock_cascade

2014/examples/simple_gemac_core/README.md

+
+This directory contains a modified version of the simple_gemac.  The
+simple_gemac is a gigabit ethernet interface that is part of the USRP
+base.
+
+The snapshot in the *simple_gemac* directory was take from:
+[]()
+
+The current source for the *simple_gemac* can be found:
+[here]()
+and
+[here]()
+
+The modificaitons in this directory are the removal of the Xilinx
+specific FIFOs and the addition of a Ptyhon verification testbench.
+
+
+The code in the *simple_gemac* has minimal changes, the main change
+is the fifo module names, they are slightly different.  This allows
+simple diff with the other bases.

2014/examples/simple_gemac_core/TODO.md

+
+#0. Need to verify based on the Xilinx FIFOs, this means building the Xilinx sim
+    models (unisim, etc.).  To build the sim models need the ISE installed.
+
+#1. Instructions to setup the simulation enviroment, including pypy instructions

2014/examples/simple_gemac_core/alt_fifo/m_delay_line_w10.v

 // File: m_delay_line_w10.v
 // Generated by MyHDL 0.9dev
-// Date: Sun Jul  6 05:10:15 2014
+// Date: Sun Jul  6 16:32:37 2014
 
 
 `timescale 1ns/10ps

2014/examples/simple_gemac_core/alt_fifo/m_fifo_2clock_cascade.py

     # @todo: the output is delayed two clock from the "read" strobe
     #   the m_fifo_async only has a delta of one (read valid strobe
     #   aligns with valid data).  Need to delay the data one more
-    #   clock cycle???
-    
-    @always(rclk.posedge)
+    #   clock cycle???    
+    # the rvld is not required but helps the 'x' propagation in simulation
+    # because the FIFO memory is not initialized (in cosimulation).
+    @always_seq(rclk.posedge, reset=reset)
     def rtl_delay():
-        dataout.next = dataout_d
+        if fbus.rvld:
+            dataout.next = dataout_d
 
     return rtl_assign1, rtl_assign2, gfifo, rtl_delay
 

2014/examples/simple_gemac_core/alt_fifo/m_fifo_2clock_cascade.v

 // File: m_fifo_2clock_cascade.v
 // Generated by MyHDL 0.9dev
-// Date: Sun Jul  6 05:10:15 2014
+// Date: Sun Jul  6 16:32:36 2014
 
 
 `timescale 1ns/10ps
 wire fbus_empty;
 wire [35:0] dataout_d;
 wire rd;
+wire fbus_rvld;
 wire fbus_full;
 wire wr;
 wire gfifo_rrst_n;
 reg gfifo_p_aempty_n;
 reg gfifo_high;
-wire gfifo_fbus_rvld;
 wire [6:0] gfifo_rgnext;
 reg [6:0] gfifo_wbin;
 reg gfifo_wfull;
 
 
 
-assign gfifo_fbus_rvld = (gfifo__rvld1 && (!gfifo__rempty));
+assign fbus_rvld = (gfifo__rvld1 && (!gfifo__rempty));
 
 
-always @(posedge rclk) begin: M_FIFO_2CLOCK_CASCADE_RTL_DELAY
-    dataout <= dataout_d;
+always @(posedge rclk, posedge reset) begin: M_FIFO_2CLOCK_CASCADE_RTL_DELAY
+    if (reset == 1) begin
+        dataout <= 0;
+    end
+    else begin
+        if (fbus_rvld) begin
+            dataout <= dataout_d;
+        end
+    end
 end
 
 endmodule

2014/examples/simple_gemac_core/alt_fifo/m_fifo_short_w11.v

 // File: m_fifo_short_w11.v
 // Generated by MyHDL 0.9dev
-// Date: Sun Jul  6 05:10:15 2014
+// Date: Sun Jul  6 16:32:37 2014
 
 
 `timescale 1ns/10ps

2014/examples/simple_gemac_core/alt_fifo/m_fifo_short_w36.v

 // File: m_fifo_short_w36.v
 // Generated by MyHDL 0.9dev
-// Date: Sun Jul  6 05:10:15 2014
+// Date: Sun Jul  6 16:32:37 2014
 
 
 `timescale 1ns/10ps

2014/examples/simple_gemac_core/simple_gemac/build

     'simple_gemac_wb.v',
     'simple_gemac.v',
     'simple_gemac_wrapper.v',
+    'simple_gemac_wrapper_tb.v'
     
     ]
 
 files = ' '.join(filelist)
 
-os.system('iverilog ' + files)
+os.system('iverilog -o simple_gemac ' + files)
+# to run the simulation ...
+#os.system('vvp simple_gemac')

2014/examples/simple_gemac_core/simple_gemac/eth_tasks_f36.v

-`timescale 1ns / 1ps
-//////////////////////////////////////////////////////////////////////////////////
-// Company: 
-// Engineer: 
-// 
-// Create Date:    14:12:55 02/18/2011 
-// Design Name: 
-// Module Name:    eth_tasks_f36 
-// Project Name: 
-// Target Devices: 
-// Tool versions: 
-// Description: 
-//
-// Dependencies: 
-//
-// Revision: 
-// Revision 0.01 - File Created
-// Additional Comments: 
-//
-//////////////////////////////////////////////////////////////////////////////////
+//`timescale 1ns / 1ps -- this files is "tick-included"
+//////////////////////////////////////////////////////////////////////////////////
+// Company: 
+// Engineer: 
+// 
+// Create Date:    14:12:55 02/18/2011 
+// Design Name: 
+// Module Name:    eth_tasks_f36 
+// Project Name: 
+// Target Devices: 
+// Tool versions: 
+// Description: 
+//
+// Dependencies: 
+//
+// Revision: 
+// Revision 0.01 - File Created
+// Additional Comments: 
+//
+//////////////////////////////////////////////////////////////////////////////////
 
 
 task SendFlowCtrl;
       tx_f36_src_rdy <= 0;
    end
 endtask // SendPacket_to_fifo36
-
+
 
 task Waiter;
 	input [31:0] wait_length;
    input [31:0] wait_length;
    input [31:0] wait_time; // This must be a multiple of 4!
    
-   integer count;
+   integer 	count;
    begin
       $display("Sending Packet From File to LL8 Len=%d, %d",data_len,$time);
-      $readmemh("simple_gemac/test_packet.mem",pkt_rom );     
-
-      while(~tx_f36_dst_rdy)
-			@(posedge sys_clk);
-			
-      tx_f36_data[31:0] <= {pkt_rom[0], pkt_rom[1], pkt_rom[2], pkt_rom[3]};
-      tx_f36_src_rdy <= 1;
-		tx_f36_data[35:34]  <= 2'b00; // 4 bytes
-      tx_f36_data[33]     <= 0; // EOF
-		tx_f36_data[32]     <= 1; // SOF
-      @(posedge sys_clk);
-      
-		// Note, this may not handle packets with sizes smaller than 8 well.
-      for(i=4;i<data_len-3;i=i+4)
-		begin
-			while(~tx_f36_dst_rdy)
-				@(posedge sys_clk);
-			tx_f36_data[31:0]   <= {pkt_rom[i], pkt_rom[i+1], pkt_rom[i+2], pkt_rom[i+3]};
-			tx_f36_data[35:34]  <= 2'b00; // 4 bytes
-			tx_f36_data[33]     <= 0; // EOF
-			tx_f36_data[32]	  <= 0; // SOF
-			@(posedge sys_clk);
-			if(i==wait_time)
-				Waiter(wait_length);
-		end
+      $readmemh("test_packet.mem",pkt_rom );     
       
       while(~tx_f36_dst_rdy)
-			@(posedge sys_clk);
-			
-      tx_f36_data[33]     <= 1; // EOF
-		tx_f36_data[35:34]  <= (data_len-i+1);
+	@(posedge sys_clk);
+      
+      tx_f36_data[31:0] <= {pkt_rom[0], pkt_rom[1], pkt_rom[2], pkt_rom[3]};
+      tx_f36_src_rdy <= 1;
+      tx_f36_data[35:34]  <= 2'b00; // 4 bytes
+      tx_f36_data[33]     <= 0;     // EOF
+      tx_f36_data[32]     <= 1;     // SOF
+      @(posedge sys_clk);
+      
+      // Note, this may not handle packets with sizes smaller than 8 well.
+      for(i=4;i<data_len-3;i=i+4)
+	begin
+	   while(~tx_f36_dst_rdy)
+	     @(posedge sys_clk);
+	   tx_f36_data[31:0]   <= {pkt_rom[i], pkt_rom[i+1], pkt_rom[i+2], pkt_rom[i+3]};
+	   tx_f36_data[35:34]  <= 2'b00; // 4 bytes
+	   tx_f36_data[33]     <= 0; // EOF
+	   tx_f36_data[32]     <= 0; // SOF	   
+	   @(posedge sys_clk);
+	   if(i==wait_time)
+	     Waiter(wait_length);
+	end
+      
+      while(~tx_f36_dst_rdy)
+	@(posedge sys_clk);
+      
+      //
+      tx_f36_data[33]     <= 1; // EOF
+      tx_f36_data[35:34]  <= (data_len-i+1);
       tx_f36_data[31:0]   <=  {pkt_rom[i], pkt_rom[i+1], pkt_rom[i+2], pkt_rom[i+3]};
       @(posedge sys_clk);
-      tx_f36_src_rdy <= 0;
-		
+      tx_f36_src_rdy <= 0;		
    end
 endtask
 

2014/examples/simple_gemac_core/simple_gemac/fifo36_to_ll8.v

-`timescale 1ns / 1ps
-//////////////////////////////////////////////////////////////////////////////////
-// Company: 
-// Engineer: 
-// 
-// Create Date:    11:47:46 02/18/2011 
-// Design Name: 
-// Module Name:    fifo36_to_ll8 
-// Project Name: 
-// Target Devices: 
-// Tool versions: 
-// Description: 
-//
-// Convert a 36-bit word, f36_data to four 8-bit outputs
-// Special inputs are:
-// f36_data[35:34] = f36_occ - number of bytes (2'b00 = 4 bytes)
-// f36_data[33]    = f36_sof - signal that this is the first byte of the data stream
-// f36_data[32]    = f36_eof - signal that this group of four bytes contains the end of
-//										 the data stream (ll_eof_n will be signalled once
-//										 f36_occ bytes have been pushed through)
-//
-// Pushes a byte every clk if src (f36_src_rdy_i) and dst (ll_dst_rdy) are ready.
-// Dependencies: 
-//
-// Revision: 
-// Revision 0.01 - File Created
-// Additional Comments: 
-//
-//////////////////////////////////////////////////////////////////////////////////
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company: 
+// Engineer: 
+// 
+// Create Date:    11:47:46 02/18/2011 
+// Design Name: 
+// Module Name:    fifo36_to_ll8 
+// Project Name: 
+// Target Devices: 
+// Tool versions: 
+// Description: 
+//
+// Convert a 36-bit word, f36_data to four 8-bit outputs
+// Special inputs are:
+// f36_data[35:34] = f36_occ - number of bytes (2'b00 = 4 bytes)
+// f36_data[33]    = f36_sof - signal that this is the first byte of the data stream
+// f36_data[32]    = f36_eof - signal that this group of four bytes contains the end of
+//										 the data stream (ll_eof_n will be signalled once
+//										 f36_occ bytes have been pushed through)
+//
+// Pushes a byte every clk if src (f36_src_rdy_i) and dst (ll_dst_rdy) are ready.
+// Dependencies: 
+//
+// Revision: 
+// Revision 0.01 - File Created
+// Additional Comments: 
+//
+//////////////////////////////////////////////////////////////////////////////////
 module fifo36_to_ll8
   (input clk, input reset, input clear,
    input [35:0] f36_data,

2014/examples/simple_gemac_core/simple_gemac/simple_gemac_wrapper.v

 //////////////////////////////////////////////////////////////////////////////////
 
 module simple_gemac_wrapper
-  #(parameter RXFIFOSIZE=9,
-    parameter TXFIFOSIZE=6)
-   (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,
-    
-    // Client FIFO Interfaces
-    input sys_clk,
-    output [35:0] rx_f36_data, output rx_f36_src_rdy, input rx_f36_dst_rdy,
-    input [35:0] tx_f36_data, input tx_f36_src_rdy, output tx_f36_dst_rdy,
-    
-    // Wishbone Interface
-    input wb_clk, input wb_rst, input wb_stb, input wb_cyc, output wb_ack, input wb_we,
-    input [7:0] wb_adr, input [31:0] wb_dat_i, output [31:0] wb_dat_o,
-    
-    // MIIM
-    inout mdio, output mdc,
-    output [79:0] debug);
-
-   wire 	  clear = 0;
-   wire [7:0] 	  rx_data, tx_data;
-   wire 	  tx_clk, tx_valid, tx_error, tx_ack;
-   wire 	  rx_clk, rx_valid, rx_error, rx_ack;
+#(
+  parameter RXFIFOSIZE=9,
+  parameter TXFIFOSIZE=6
+ )
+(
+ 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,
+ 
+ // Client FIFO Interfaces
+ input 	       sys_clk,
+ output [35:0] rx_f36_data, output rx_f36_src_rdy, input rx_f36_dst_rdy,
+ input [35:0]  tx_f36_data, input tx_f36_src_rdy, output tx_f36_dst_rdy,
+ 
+ // Wishbone Interface
+ input 	       wb_clk, input wb_rst, input wb_stb, input wb_cyc, output wb_ack, input wb_we,
+ input [7:0]   wb_adr, input [31:0] wb_dat_i, output [31:0] wb_dat_o,
+ 
+ // MIIM
+ inout 	       mdio, output mdc,
+ output [79:0] debug
+ );
    
-   wire [47:0] 	  ucast_addr, mcast_addr;
-   wire 	  pass_ucast, pass_mcast, pass_bcast, pass_pause, pass_all;
-   wire 	  pause_req;
-   wire 	  pause_request_en, pause_respect_en;
-   wire [15:0] 	  pause_time, pause_thresh, pause_time_req, rx_fifo_space;
+   wire        clear = 0;
+   wire [7:0]  rx_data, tx_data;
+   wire        tx_clk, tx_valid, tx_error, tx_ack;
+   wire        rx_clk, rx_valid, rx_error, rx_ack;
    
-   wire 	  tx_reset, rx_reset;
+   wire [47:0] ucast_addr, mcast_addr;
+   wire        pass_ucast, pass_mcast, pass_bcast, pass_pause, pass_all;
+   wire        pause_req;
+   wire        pause_request_en, pause_respect_en;
+   wire [15:0] pause_time, pause_thresh, pause_time_req, rx_fifo_space;
+   
+   wire        tx_reset, rx_reset;
    reset_sync reset_sync_tx (.clk(tx_clk),.reset_in(reset),.reset_out(tx_reset));
    reset_sync reset_sync_rx (.clk(rx_clk),.reset_in(reset),.reset_out(rx_reset));
-	wire [39:0] simple_gemac_debug;
-
+   wire [39:0] simple_gemac_debug;
+   
    simple_gemac simple_gemac
      (.clk125(clk125),  .reset(reset),
       .GMII_GTX_CLK(GMII_GTX_CLK), .GMII_TX_EN(GMII_TX_EN),  
       .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),
-		.debug(simple_gemac_debug)
+      .debug(simple_gemac_debug)
       );
    
-	
+   
    simple_gemac_wb simple_gemac_wb
      (.wb_clk(wb_clk), .wb_rst(wb_rst),
       .wb_cyc(wb_cyc), .wb_stb(wb_stb), .wb_ack(wb_ack), .wb_we(wb_we),
       .pass_pause(pass_pause), .pass_all(pass_all), 
       .pause_respect_en(pause_respect_en), .pause_request_en(pause_request_en),
       .pause_time(pause_time), .pause_thresh(pause_thresh));
-
+   
+   //=====================================================================
    // RX FIFO Chain
-   wire 	  rx_ll_sof, rx_ll_eof, rx_ll_src_rdy, rx_ll_dst_rdy;
+   wire        rx_ll_sof, rx_ll_eof, rx_ll_src_rdy, rx_ll_dst_rdy;
    
-   wire 	  rx_ll_sof2, rx_ll_eof2, rx_ll_src_rdy2, rx_ll_dst_rdy2;
-   wire 	  rx_ll_sof2_n, rx_ll_eof2_n, rx_ll_src_rdy2_n, rx_ll_dst_rdy2_n;
+   wire        rx_ll_sof2, rx_ll_eof2, rx_ll_src_rdy2, rx_ll_dst_rdy2;
+   wire        rx_ll_sof2_n, rx_ll_eof2_n, rx_ll_src_rdy2_n, rx_ll_dst_rdy2_n;
    
-   wire [7:0] 	  rx_ll_data, rx_ll_data2;
+   wire [7:0]  rx_ll_data, rx_ll_data2;
    
-   wire [35:0] 	  rx_f36_data_int1;
-   wire 	  rx_f36_src_rdy_int1, rx_f36_dst_rdy_int1;
+   wire [35:0] rx_f36_data_int1;
+   wire        rx_f36_src_rdy_int1, rx_f36_dst_rdy_int1;
    
    rxmac_to_ll8 rx_adapt
      (.clk(rx_clk), .reset(rx_reset), .clear(1'b0),
       .rx_data(rx_data), .rx_valid(rx_valid), .rx_error(rx_error), .rx_ack(rx_ack),
       .ll_data(rx_ll_data), .ll_sof(rx_ll_sof), .ll_eof(rx_ll_eof), .ll_error(),  // error also encoded in sof/eof
       .ll_src_rdy(rx_ll_src_rdy), .ll_dst_rdy(rx_ll_dst_rdy));
-
+   
    ll8_shortfifo rx_sfifo
      (.clk(rx_clk), .reset(rx_reset), .clear(1'b0),
       .datain(rx_ll_data), .sof_i(rx_ll_sof), .eof_i(rx_ll_eof),
       .error_i(1'b0), .src_rdy_i(rx_ll_src_rdy), .dst_rdy_o(rx_ll_dst_rdy),
       .dataout(rx_ll_data2), .sof_o(rx_ll_sof2), .eof_o(rx_ll_eof2),
       .error_o(), .src_rdy_o(rx_ll_src_rdy2), .dst_rdy_i(rx_ll_dst_rdy2));
-
+   
    assign rx_ll_dst_rdy2  = ~rx_ll_dst_rdy2_n;
    assign rx_ll_src_rdy2_n = ~rx_ll_src_rdy2;
    assign rx_ll_sof2_n 	  = ~rx_ll_sof2;
       .ll_data(rx_ll_data2), .ll_sof_n(rx_ll_sof2_n), .ll_eof_n(rx_ll_eof2_n),
       .ll_src_rdy_n(rx_ll_src_rdy2_n), .ll_dst_rdy_n(rx_ll_dst_rdy2_n),
       .f36_data(rx_f36_data_int1), .f36_src_rdy_o(rx_f36_src_rdy_int1), .f36_dst_rdy_i(rx_f36_dst_rdy_int1));
-
+   
    m_fifo_2clock_cascade  u_rx_2clk_fifo
      (.wclk(rx_clk), .datain(rx_f36_data_int1), 
       .src_rdy_i(rx_f36_src_rdy_int1), .dst_rdy_o(rx_f36_dst_rdy_int1), .space(rx_fifo_space),
       .occupied(), 
       .reset(reset));
    
+   //=====================================================================   
    // TX FIFO Chain
-   wire 	  tx_ll_sof, tx_ll_eof, tx_ll_src_rdy, tx_ll_dst_rdy;
-   wire 	  tx_ll_sof2, tx_ll_eof2, tx_ll_src_rdy2, tx_ll_dst_rdy2;
-   wire 	  tx_ll_sof2_n, tx_ll_eof2_n, tx_ll_src_rdy2_n, tx_ll_dst_rdy2_n;
-   wire [7:0] 	  tx_ll_data, tx_ll_data2;
-   wire [35:0] 	  tx_f36_data_int1;
-   wire 	  tx_f36_src_rdy_int1, tx_f36_dst_rdy_int1;
+   wire        tx_ll_sof, tx_ll_eof, tx_ll_src_rdy, tx_ll_dst_rdy;
+   wire        tx_ll_sof2, tx_ll_eof2, tx_ll_src_rdy2, tx_ll_dst_rdy2;
+   wire        tx_ll_sof2_n, tx_ll_eof2_n, tx_ll_src_rdy2_n, tx_ll_dst_rdy2_n;
+   wire [7:0]  tx_ll_data, tx_ll_data2;
+   wire [35:0] tx_f36_data_int1;
+   wire        tx_f36_src_rdy_int1, tx_f36_dst_rdy_int1;
    
    m_fifo_2clock_cascade u_tx_2clk_fifo
      (.wclk(sys_clk), .datain(tx_f36_data), 
       .reset(reset));
    
    // Converts 36-bit word to 4*8 bit outpus plus control signals
-   wire [2:0] 	  fifo36_to_ll8_debug;
+   wire [2:0]  fifo36_to_ll8_debug;
    fifo36_to_ll8 fifo36_to_ll8
      (.clk(tx_clk), .reset(tx_reset), .clear(clear),
-      .f36_data(tx_f36_data_int1), .f36_src_rdy_i(tx_f36_src_rdy_int1), .f36_dst_rdy_o(tx_f36_dst_rdy_int1),
+      .f36_data(tx_f36_data_int1), .f36_src_rdy_i(tx_f36_src_rdy_int1), 
+      .f36_dst_rdy_o(tx_f36_dst_rdy_int1),
       .ll_data(tx_ll_data2), .ll_sof_n(tx_ll_sof2_n), .ll_eof_n(tx_ll_eof2_n),
       .ll_src_rdy_n(tx_ll_src_rdy2_n), .ll_dst_rdy_n(tx_ll_dst_rdy2_n),
-		.debug(fifo36_to_ll8_debug));
-
+      .debug(fifo36_to_ll8_debug));
+   
    assign tx_ll_sof2 	    = ~tx_ll_sof2_n;
    assign tx_ll_eof2 	    = ~tx_ll_eof2_n;
    assign tx_ll_src_rdy2    = ~tx_ll_src_rdy2_n;
       .dataout(tx_ll_data), .sof_o(tx_ll_sof), .eof_o(tx_ll_eof),
       .error_o(), .src_rdy_o(tx_ll_src_rdy), .dst_rdy_i(tx_ll_dst_rdy));
    
-	wire [2:0] ll8_to_txmac_xferstate;
+   wire [2:0]  ll8_to_txmac_xferstate;
    ll8_to_txmac ll8_to_txmac
      (.clk(tx_clk), .reset(tx_reset), .clear(clear),
       .ll_data(tx_ll_data), .ll_sof(tx_ll_sof), .ll_eof(tx_ll_eof),
       .ll_src_rdy(tx_ll_src_rdy), .ll_dst_rdy(tx_ll_dst_rdy),
       .tx_data(tx_data), .tx_valid(tx_valid), .tx_error(tx_error), .tx_ack(tx_ack),
-		.debug(ll8_to_txmac_xferstate));
-
-	// Flow control
+      .debug(ll8_to_txmac_xferstate));
+   
+   // Flow control
    flow_ctrl_rx flow_ctrl_rx
      (.pause_request_en(pause_request_en), .pause_time(pause_time), .pause_thresh(pause_thresh),
       .rx_clk(rx_clk), .rx_reset(rx_reset), .rx_fifo_space(rx_fifo_space),
       .tx_clk(tx_clk), .tx_reset(tx_reset), .pause_req(pause_req), .pause_time_req(pause_time_req));
    
    
-	// Debug signals
-	wire [79:0] debug_tx;
-	wire [31:0]	debug_rx;
-	
+   // Debug signals
+   wire [79:0] debug_tx;
+   wire [31:0] debug_rx;
+   
    assign debug_tx  = { tx_f36_data_int1[31:0], fifo36_to_ll8_debug, simple_gemac_debug[39:32], {reset, tx_reset, ll8_to_txmac_xferstate}, { tx_ll_data },
 			{ tx_ll_sof, tx_ll_eof, tx_ll_src_rdy, tx_ll_dst_rdy, 
 			  tx_ll_sof2, tx_ll_eof2, tx_ll_src_rdy2, tx_ll_dst_rdy2 },
 			  rx_ll_sof2, rx_ll_eof2, rx_ll_src_rdy2, rx_ll_dst_rdy2 },
 			{ rx_valid, rx_error, rx_ack, rx_f36_src_rdy_int1, rx_f36_dst_rdy_int1, rx_f36_data_int1[34:32]},
 			{ rx_data} };
-
+   
    assign debug  = debug_tx;
-
+   
 endmodule // simple_gemac_wrapper

2014/examples/simple_gemac_core/simple_gemac/simple_gemac_wrapper_tb.v

-////////////////////////////////////////////////////////////////////////////////
-// Company: 
-// Engineer:
-//
-// Create Date:   14:12:04 02/18/2011
-// Design Name:   simple_gemac_wrapper
-// Module Name:   C:/Users/Administrator/Desktop/Xilinx/atlys_ethernet_test/wishbone//simple_gemac_wrapper_tb.v
-// Project Name:  atlys_ethernet_test
-// Target Device:  
-// Tool versions:  
-// Description: 
-//
-// Verilog Test Fixture created by ISE for module: simple_gemac_wrapper
-//
-// Dependencies:
-// 
-// Revision:
-// Revision 0.01 - File Created
-// Additional Comments:
-// 
-////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+// Company: 
+// Engineer:
+//
+// Create Date:   14:12:04 02/18/2011
+// Design Name:   simple_gemac_wrapper
+// Module Name:   C:/Users/Administrator/Desktop/Xilinx/atlys_ethernet_test/wishbone//simple_gemac_wrapper_tb.v
+// Project Name:  atlys_ethernet_test
+// Target Device:  
+// Tool versions:  
+// Description: 
+//
+// Verilog Test Fixture created by ISE for module: simple_gemac_wrapper
+//
+// Dependencies:
+// 
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// 
+////////////////////////////////////////////////////////////////////////////////
 
-module simple_gemac_wrapper_tb;
+module tb_simple_gemac;
 `include "eth_tasks_f36.v"
      
    reg reset   = 1;
    wire        rx_f36_src_rdy;
    wire        rx_f36_dst_rdy = 1;
    
-   simple_gemac_wrapper simple_gemac_wrapper
+   simple_gemac_wrapper DUT
      (.clk125(eth_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),
       .debug() );
    
    initial $dumpfile("simple_gemac_wrapper_tb.vcd");
-   initial $dumpvars(0,simple_gemac_wrapper_tb);
+   initial $dumpvars(0,tb_simple_gemac); //simple_gemac_wrapper_tb
 
    integer i; 
    reg [7:0] pkt_rom[0:16383];
      for (i=0;i<16383;i=i+1)
        pkt_rom[i] <= 8'hAA;
 
+   integer pkt_test = 0;
    initial
      begin
+	pkt_test = 0;	
 	@(negedge reset);
 	repeat (10)
 	  @(posedge wb_clk);
 	WishboneWR(8,32'hC0D0_A1B1); // ucast_addr_l
 	WishboneWR(12,16'h0000); // mcast_addr_h
 	WishboneWR(16,32'h0000_0000); // mcast_addr_l
-	
-	$display("Setting MII bits, %d", $time);
-	
-	WishboneWR(20, 8'h08); // Set MDIO divider to 8 and nopre to 0.
-	
-	
-	//WishboneWR(24,  // Set address to the 
-	//$display("Done setting MII, %d	", $time);
-	
+	
+	$display("Setting MII bits, %d", $time);
+	
+	WishboneWR(20, 8'h08); // Set MDIO divider to 8 and nopre to 0.
+	
+	
+	//WishboneWR(24,  // Set address to the 
+	//$display("Done setting MII, %d	", $time);
+	
 //	@(posedge eth_clk);
 //	SendFlowCtrl(16'h0007);  // Send flow control
 //	@(posedge eth_clk);
 //	@(posedge eth_clk); 
 
 	repeat (1000)
-	  @(posedge sys_clk);
- 	$display("First packet, %d", $time);
- 	
+	  @(posedge sys_clk);
+ 	$display("First packet, %d", $time);
+ 	pkt_test = 1;	
 	SendPacket_to_fifo36(32'hA0B0C0D0,10);    // This packet gets dropped by the filters
 	repeat (1000)
 	  @(posedge sys_clk);
-
-	$display("Second packet, %d", $time);
-
+	
+	$display("Second packet, %d", $time);
+	pkt_test = 2;	
 	SendPacket_to_fifo36(32'hAABBCCDD,100);    // This packet gets dropped by the filters
 	repeat (10)
-	  @(posedge sys_clk);
-	
-	#50000;	
+	  @(posedge sys_clk);
+	
+	#50000;	
 	$display("Normal packet, %d", $time);
  	SendPacketFromFile_f36(60,0,0);  // The rest are valid packets
 	repeat (10)
 	  @(posedge sys_clk);
-
-	#50000;
+	
+	#50000;
 	$display("Huge packet, %d", $time);
  	SendPacketFromFile_f36(10000,0,0);
+	
 //	repeat (10)
 //	  @(posedge sys_clk);
 //	SendPacketFromFile_f36(62,0,0);

2014/examples/simple_gemac_core/test/_gemac_filelist.py

-
-
-filelist = [
-
-    '../simple_gemac/miim/eth_miim.v',
-    '../simple_gemac/miim/eth_clockgen.v',
-    '../simple_gemac/miim/eth_outputcontrol.v',
-    '../simple_gemac/miim/eth_shiftreg.v',
-
-    # myhdl fifo replacements
-    '../alt_fifo/m_fifo_2clock_cascade.v',
-    '../alt_fifo/m_fifo_short_w36.v',
-    '../alt_fifo/m_fifo_short_w11.v',
-    '../alt_fifo/m_delay_line_w10.v',
-
-    '../simple_gemac/ll8_shortfifo.v',
-    '../simple_gemac/ll8_to_fifo36.v',
-    '../simple_gemac/fifo36_to_ll8.v',
-    '../simple_gemac/ll8_to_txmac.v',
-    '../simple_gemac/rxmac_to_ll8.v',
-    '../simple_gemac/oneshot_2clk.v',
-    '../simple_gemac/reset_sync.v',
-    '../simple_gemac/crc.v',
-    '../simple_gemac/address_filter.v',
-    '../simple_gemac/flow_ctrl_rx.v',
-    '../simple_gemac/flow_ctrl_tx.v',
-    '../simple_gemac/simple_gemac_rx.v',
-    '../simple_gemac/simple_gemac_tx.v',
-    '../simple_gemac/simple_gemac_wb.v',
-    '../simple_gemac/simple_gemac.v',
-    '../simple_gemac/simple_gemac_wrapper.v',
-    
-    ]

2014/examples/simple_gemac_core/test/_sgem_eth.py

+
+from __future__ import division
+from __future__ import print_function
+
+from myhdl import *
+
+MinPktLen = (8 + 6 + 6 + 4 + 2 + 4)
+
+class EthernetByteStream(object):
+    """
+    Each Ethernet interface (MII, RMII, GMII) needs to create a 
+    byte-stream to connect to the Ethernet network emulation.
+    """
+    def __init__(self, clk, bs, dv, er):
+        self.clk = clk
+        self.bs = bs
+        self.dv = dv
+        self.er = er
+
+class EthernetPacket(object):
+    """
+    """
+    def __init__(self):
+        # @todo: max ethernet packet is ??? bytes, use array.array('B')
+        #        instead (less memory, unless numerous outstanding pkts).
+        self.bytes = []   # the raw bytes
+        self.crc = None   # packet crc
+        self.mac_dst = None
+        self.mac_src = None
+        self.tag = None
+        self.complete = False
+
+    def calc_crc(self):
+        assert len(self.bytes) >= MinPktLen
+        
+    def captured(self):
+        """ when a complete packet is captured, generate the fields 
+        """
+        assert len(self.bytes) >= MinPktLen
+
+        self.complete = True
+
+    def append(self, byte):
+        if not self.complete:
+            self.bytes.append(byte)
+
+# @todo: create an Ethernet object that takes various interfaces (GMII,
+#        RMII, MII) and creates byte streams and has various methods 
+#        to decode packets etc.
+class Ethernet(object):
+    """
+    This is a simple ethernet emulation, it works on byte-streams and 
+    not single differential lines.  This can connect different Ethernet
+    interfaces (MII, RMII, GMII) as long as the generate the byte streams
+    (Ethernet standard define on octets (bytes) should always be complete
+     bytes).
+    """
+    def __init__(self, delay=3):
+        self.nif = 0        # number of interfaces
+        self.delay = delay  # a time-of-flight delay
+
+        # list of all the interfaces (EthernetByteStreams) connected
+        self.txif = []
+        self.rxif = []
+
+        # currently transmitting interface (only one at a time)
+        self.txbs = txbs
+        self.txdv = txdv
+        self.txer = txer
+        self.txck = txck
+
+        # only one transmitter at a time, if the packetizer is enabled
+        # all captured packets will be added to the list
+        self.pkts = []
+        
+    def info(self):
+        """
+        """
+        # @todo generate a string with a ton of info about the number
+        #   of connections etc.
+        pass
+
+    def add(self, intf):
+        assert isinstance(intf, (MII, RMII, GMII))
+        assert hasattr(intf, tx_eth)
+        assert hasattr(intf, rx_eth)
+        # @todo: connect the interfaces
+
+        self.txif.append(intf.tx_eth)
+        self.rxif.append(intf.rx_eth)
+        self.nif += 1
+        
+    def m_route(self, clock):
+        """
+        currently all the interfaces are connected, the byte-streams (bs)
+        from each interface, including looping back to itself, broadcast
+        to all.
+        """
+        
+        # find a transmitting interface
+        # currently the method to resolve collisions is winner take
+        # all the first tx inteface 
+        c_txi = Signal(-1) # current transmiting interface
+        @always_comb
+        def emu_find_tx():
+            for ii,txi in enumerate(self.txif):
+                if txi.dv:
+                    c_txi.next = ii
+        
+        # currently transmitting interface
+        txbs = Signal(intbv(0)[8:], delay=self.delay)
+        txdv = Signal(bool(0),      delay=self.delay)
+        txer = Signal(bool(0),      delay=self.delay)
+        txck = Signal(bool(0),      delay=self.delay)
+
+        # object refernces so the packet decoder can do its job
+        self.txbs = txbs
+        self.txdv = txdv
+        self.txer = txer
+        self.txck = txck
+
+        # map the tranmitting byte-stream to all recievers
+        @always_comb
+        def emu_map_tx():
+            txck.next = self.txif[c_txi].clk
+            txbs.next = self.txif[c_txi].bs
+
+        @always_comb
+        def emu_route_rx():
+            if c_txi >= 0 and c_txi < len(self.rxif):
+                for rxi in self.rxif:
+                    rxi.bs.next = txbs
+                    rxi.dv.next = txdv
+                    rxi.er.next = txer
+                    rxi.clk.next = txck
+                
+
+        return emu_find_tx, emu_map_tx, emu_route_rx
+
+    def packetize_byte_stream(self, clock):
+        """ monitor a bytes stream and decode the packets
+                
+        given a byte-stream (bs), data valid (dv) and errror (er) this
+        will monitor and capture packets.  A packet 
+        summary of imporant ethernet standard/information:
+        """
+        assert isinstance(pkt_lst, list)
+        assert len(bs) == 8
+
+        states = enum("START",     # wait for a packet
+                      "PREAMBLE",  # get the preamble
+                      "HEADER",    # get the header
+                      "PAYLOAD",   # get the payload
+                      "TIMEOUT",   # timeout occurred 
+                      "ERROR",     # some kind of error occurred
+                      "IDELAY",    # wait for 
+        )
+
+        bs = self.txbs
+
+        @instance
+        def mon_decode_pkt():
+            state = states.START
+            nbytes = 0
+            idelay = 0
+            pkt = None
+
+            while True:
+                yield clock.posedge
+                      
+                #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+                if state == states.START:
+                    # wait for a packet to start arriving
+                    if dv and bs == 0x55:
+                        pkt = EthernetPacket()
+                        pkt.append(bs)
+                        nbytes += 1
+                        state = states.PREAMBLE
+
+                #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+                elif state == states.PREAMBLE:
+                    # need to get 6 more 0x55 and SOF
+                    if dv:
+                        if nbytes < 7 and bs == 0x55:
+                            pkt.append(bs)
+                            nbytes += 1
+                        elif nbytes == 8:
+                            pkt.append(bs)
+                            nbytes += 1
+                            state = states.HEADER
+                        else:
+                            # error, unexpected wait for intergap
+                            state = states.ERROR
+
+                #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+                elif state == states.HEADER:
+                    pass
+                        
+
+        return mon_decode_pkt
+

2014/examples/simple_gemac_core/test/_sgem_filelist.py

+
+filelist = [
+
+    '../simple_gemac/miim/eth_miim.v',
+    '../simple_gemac/miim/eth_clockgen.v',
+    '../simple_gemac/miim/eth_outputcontrol.v',
+    '../simple_gemac/miim/eth_shiftreg.v',
+
+    # myhdl fifo replacements
+    '../alt_fifo/m_fifo_2clock_cascade.v',
+    '../alt_fifo/m_fifo_short_w36.v',
+    '../alt_fifo/m_fifo_short_w11.v',
+    '../alt_fifo/m_delay_line_w10.v',
+
+    '../simple_gemac/ll8_shortfifo.v',
+    '../simple_gemac/ll8_to_fifo36.v',
+    '../simple_gemac/fifo36_to_ll8.v',
+    '../simple_gemac/ll8_to_txmac.v',
+    '../simple_gemac/rxmac_to_ll8.v',
+    '../simple_gemac/oneshot_2clk.v',
+    '../simple_gemac/reset_sync.v',
+    '../simple_gemac/crc.v',
+    '../simple_gemac/address_filter.v',
+    '../simple_gemac/flow_ctrl_rx.v',
+    '../simple_gemac/flow_ctrl_tx.v',
+    '../simple_gemac/simple_gemac_rx.v',
+    '../simple_gemac/simple_gemac_tx.v',
+    '../simple_gemac/simple_gemac_wb.v',
+    '../simple_gemac/simple_gemac.v',
+    '../simple_gemac/simple_gemac_wrapper.v',
+    
+    ]

2014/examples/simple_gemac_core/test/_sgem_gmii.py

+
+from __future__ import division
+from __future__ import print_function
+
+from myhdl import *
+
+from _sgem_eth import EthernetByteStream
+
+
+class GMII(object):
+    """
+    """
+
+    def __init__(self):
+        # outputs (from DUT)
+        self.tx_clk = Signal(bool(0))     # 125 MHz clock for GMII
+        self.tx_en = Signal(bool(0))      # enable (data is valid)
+        self.tx_er = Signal(bool(0))      # error (corrupt the packet)
+        self.txd = Signal(intbv(0)[8:])   # data
+        
+        # inputs (to DUT)
+        self.rx_clk = Signal(bool(0))     # recieve clock, 125 MHz
+        self.rx_dv = Signal(bool(0))      # data valid
+        self.rx_er = Signal(bool(0))      # error on data
+        self.rxd = Signal(intbv(0)[8:])   # data
+
+        self.force_error = Signal(bool(0))
+        self.force_dat_err = Signal(intbv(0)[8:])
+
+        # get the byte-streams to connect to Ethernet emulation
+        self.tx_eth = EthernetByteStream(self.tx_clk, self.txd,
+                                         self.tx_en,  self.tx_er)
+        self.rx_eth = EthernetByteStream(self.rx_clk, self.rxd,
+                                         self.rx_dv,  self.rx_er)
+        self.txl = []
+        self.rxl = []
+
+    def clear(self):
+        self.txl = []
+        self.rxl = []
+
+    def m_loopback(self):
+        """ loopback the interface
+        """
+        force_error = self.force_error
+        force_dat_err = self.force_dat_err
+
+        @always_comb
+        def mlp():
+            self.rx_dv.next  = self.tx_en
+            self.rx_er.next  = self.tx_er | force_error
+            self.rxd.next    = self.txd ^ force_dat_err
+            self.rx_clk.next = self.tx_clk
+
+        return mlp
+
+    def m_tx_monitor(self):    
+        @always(self.tx_clk.posedge)
+        def montx():
+            if self.tx_en:
+                self.txl.append(int(self.txd))
+
+        return montx
+
+    def m_rx_monitor(self):
+        @always(self.rx_clk.posedge)
+        def monrx():
+            if self.rx_dv:
+                self.rxl.append(int(self.rxd))
+
+        return monrx
+
+    def dump_monitors(self, pktb=None):
+        """ dumpy the monitor buffers (lists)
+        pktb : packet buffer (list)
+        """
+        ln = min(len(self.txl), len(self.rxl))
+        print("  len(txl) %d,  len(rxl) %d  " % (len(self.txl), len(self.rxl)))
+        for ii in range(ln):
+            print("  [%4d]: %02X  %02X  " % (ii, self.txl[ii], self.rxl[ii]))
+
+    

2014/examples/simple_gemac_core/test/_sgem_prep_cosim.py

+
+import os
+
+from myhdl import *
+from _sgem_filelist import filelist
+
+#=====================================================================
+# @todo: move to a separate file
+def prep_cosim(
+    args,
+    clk125=None,
+    reset=None,
+    gmii=None,
+    sys_clk=None,
+    stintf=None,
+    wb=None,
+    #mdio=None,
+    #mdc=None            
+):
+    """
+    """
+    global filelist
+    files = filelist + ['tb_simple_gemac.v']
+    print("compiling ...")
+    cmd = "iverilog -o simple_gemac %s " % (" ".join(files))
+    os.system(cmd)
+
+    if not os.path.exists('vcd'):
+        os.makedirs('vcd')
+
+    print("cosimulation setup ...")
+    cmd = "vvp -m ./myhdl.vpi simple_gemac"
+
+    gcosim = Cosimulation(cmd,
+        clk125=clk125, 
+        reset=reset,
+        # ethernet phy interface
+        GMII_GTX_CLK=gmii.tx_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,
+        # internal logic 
+        sys_clk=sys_clk,
+        rx_f36_data=stintf.rx_data, 
+        rx_f36_src_rdy=stintf.rx_src_rdy, 
+        rx_f36_dst_rdy=stintf.rx_dst_rdy,
+        tx_f36_data=stintf.tx_data, 
+        tx_f36_src_rdy=stintf.tx_src_rdy, 
+        tx_f36_dst_rdy=stintf.tx_dst_rdy,
+
+        # wishbone interface (device perspective)
+        wb_clk=wb.clk_i,
+        wb_rst=wb.rst_i,
+        wb_stb=wb.stb_i,
+        wb_cyc=wb.cyc_i,
+        wb_ack=wb.ack_o,
+        wb_we=wb.we_i,
+        wb_adr=wb.adr_i,
+        wb_dat_i=wb.dat_i,
+        wb_dat_o=wb.dat_o
+
+        # miim
+        #mdio=mdi, mdc=mdc 
+    )
+
+    return gcosim
+

2014/examples/simple_gemac_core/test/_sgem_stif.py

+
+from __future__ import division
+from __future__ import print_function
+
+from myhdl import *
+
+
+class StreamIntf(object):
+    def __init__(self, eth_clk, sys_clk, W=36):
+        # out of 
+        self.eth_clk = eth_clk
+        self.sys_clk = sys_clk
+
+        self.rx_data = Signal(intbv(0)[W:])
+        self.rx_src_rdy = Signal(bool(0))
+        self.rx_dst_rdy = Signal(bool(0))
+        
+        # into
+        self.tx_data = Signal(intbv(0)[W:])
+        self.tx_src_rdy = Signal(bool(0))
+        self.tx_dst_rdy = Signal(bool(0))
+
+    def m_rx_packets(self, clock, reset):
+        # recieve packets into a buffer
+        self.pkt_buffer = []        
+        word_cnt = Signal(0)
+
+        @always_seq(clock.posedge, reset=reset)
+        def mon_rx_pkts():
+            # always ready to receive packet words
+            self.rx_dst_rdy.next = True
+
+            # if a new packet word arrives print and save (for now)
+            if self.rx_src_rdy:
+                print("::%08d:: new pkt word %09X, words %4d" % (now(), self.rx_data, word_cnt)) 
+                self.pkt_buffer.append(self.rx_data)
+                word_cnt.next = word_cnt + 1
+
+        return mon_rx_pkts
+
+    def t_tx_packet_sp(self, data_start, data_len):
+        """ send a simple packet
+        This is a replication of the original testbench send
+        packet task.  This should be made genericer in the future!
+        
+        36 bit bus
+          35:34 : empty bytes (if 4 bytes used == 00)
+          33    : end of frame (end of packet), EOF
+          32    : start of frame (start of packet), SOF
+          31:0  : 4 bytes of data
+          
+        Currently use the _sp to indicate this is a replication of 
+        the original tasks.
+        """
+        # transmit a packet, the packet should be in a Python byte
+        # array pkt = array.array('B', ...)
+        #txd = int('00' + '0' + '1' + bin(data_start, 32), 2)
+        txd = concat('00', '0', '1', intbv(data_start)[32:])
+        self.tx_data.next = txd
+        self.tx_src_rdy.next = True
+        count = 2
+        while count < data_len:
+            while not self.tx_dst_rdy:
+                yield self.sys_clk.posedge
+            yield self.sys_clk.posedge
+            self.tx_data.next[32:0] = self.tx_data[32:0] + 0x01010101
+            count = count + 4
+            self.tx_data.next[32] = 0
+
+        self.tx_data.next[32] = 1
+        while not self.tx_dst_rdy:
+            yield self.sys_clk.posedge
+        yield self.sys_clk.posedge
+        self.tx_src_rdy.next = False
+
+    def t_tx_packet_from_file_sp(self, data_len, nwait=0, fn='test_packet.mem'):
+        """ send a packet from a file
+        This is a replication of the original testbench task to send
+        a packet from a file.
+
+        Currently use the _sp to indicate this is a replication of 
+        the original tasks.
+        """
+        
+        fp = open(fn, 'r')
+        N = data_len + (data_len % 4)
+        pkt_mem = [intbv(0)[8:] for _ in range(N)]
+        for ii in range(data_len):
+            byte = fp.readline()
+            pkt_mem[ii][:] = int(byte, 16)
+            
+        self.pkt_mem = pkt_mem
+
+        # wait for the destination (gemac TX FIFO) to be ready
+        while not self.tx_dst_rdy:
+            yield self.sys_clk.posedge
+
+        txd = concat(pkt_mem[0], pkt_mem[1], pkt_mem[2], pkt_mem[3])
+        self.tx_data.next[32:0] = txd
+        self.tx_data.next[36:34] = intbv('00')   # 4 bytes are valid
+        self.tx_data.next[33] = 0                # EOF
+        self.tx_data.next[32] = 1                # SOF
+        self.tx_src_rdy.next = True
+        yield self.sys_clk.posedge
+        self.tx_src_rdy.next = False
+
+        for ii in range(4, data_len-3, 4):
+            while not self.tx_dst_rdy:
+                yield self.sys_clk.posedge
+            txd = concat(pkt_mem[ii], pkt_mem[ii+1], pkt_mem[ii+2], pkt_mem[ii+3])
+            self.tx_data.next[32:0] = txd
+            self.tx_data.next[36:32] = 0
+            self.tx_src_rdy.next = True
+            yield self.sys_clk.posedge
+            self.tx_src_rdy.next = False
+            for jj in range(nwait):
+                yield self.sys_clk
+
+        while not self.tx_dst_rdy:
+            yield self.sys_clk.posedge
+
+        # ok, should be at the end of the packet now, if the packet len
+        # is not a multiple of four need to indicate the number of empty
+        # bytes, this appears to be data_len-ii+1
+        #ii = ii + 4
+        Ne = (data_len-ii) % 4
+        print("@D: last index %d, data_len %d, N %d, Ne %d" % (ii, data_len, N, Ne))
+        txd = concat(pkt_mem[ii], pkt_mem[ii+1], pkt_mem[ii+2], pkt_mem[ii+3])
+        self.tx_data.next[32:0] = txd
+        self.tx_data.next[36:34] = Ne
+        self.tx_data.next[33] = 1    # EOF
+        self.tx_data.next[32] = 0    # SOF
+        self.tx_src_rdy.next = True
+        yield self.sys_clk.posedge
+        self.tx_src_rdy.next = False
+        

2014/examples/simple_gemac_core/test/tb_simple_gemac.v

+`timescale 1ps / 1ps
 
 module tb_simple_gemac;
 
    /*output*/  wire [79:0] debug;       
    
    initial begin
-      $dumpfile("vcd/_tb_simpe_gemac.vcd");
+      $dumpfile("vcd/_tb_simple_gemac.vcd");
       $dumpvars(0, tb_simple_gemac);
    end
 

2014/examples/simple_gemac_core/test/test_simple_gemac.py

 
 from mn.system import Wishbone
 
-from _gemac_filelist import filelist
+from _sgem_prep_cosim import prep_cosim
+from _sgem_gmii import GMII
+from _sgem_stif import StreamIntf
 
 
-class GMII(object):
-    def __init__(self):
-        # outputs (from DUT)
-        self.tx_clk = Signal(bool(0))
-        self.tx_en = Signal(bool(0))
-        self.tx_er = Signal(bool(0))
-        self.txd = Signal(intbv(0)[8:])
-        
-        # inputs (to DUT)
-        self.rx_clk = Signal(bool(0))
-        self.rx_dv = Signal(bool(0))
-        self.rx_er = Signal(bool(0))
-        self.rxd = Signal(intbv(0)[8:])
-
-class StreamIntf(object):
-    def __init__(self, W=36):
-        # out of 
-        self.rx_data = Signal(intbv(0)[W:])
-        self.rx_src_rdy = Signal(bool(0))
-        self.rx_dst_rdy = Signal(bool(0))
-        
-        # into
-        self.tx_data = Signal(intbv(0)[W:])
-        self.tx_src_rdy = Signal(bool(0))
-        self.tx_dst_rdy = Signal(bool(0))
-
-    def m_rx_packets(self, clock, reset):
-        # recieve packets into a buffer
-        pass
-
-    def t_tx_packet(self, pkt):
-        # transmit a packet, the packet should be in a Python byte
-        # array pkt = array.array('B', ...)
-        pass
-
-
-#=====================================================================
-def _prep_cosim(
-    args,
-    clk125=None,
-    reset=None,
-    gmii=None,
-    sys_clk=None,
-    stintf=None,
-    wb=None,
-    #mdio=None,
-    #mdc=None            
-):
-    """
-    """
-    global filelist
-    files = filelist + ['tb_simple_gemac.v']
-    print("compiling ...")
-    cmd = "iverilog -o simple_gemac %s " % (" ".join(files))
-    os.system(cmd)
-
-    if not os.path.exists('vcd'):
-        os.makedirs('vcd')
-
-    print("cosimulation setup ...")
-    cmd = "vvp -m ../myhdl.vpi simple_gemac"
-
-    gcosim = Cosimulation(cmd,
-        clk125=clk125, 
-        reset=reset,
-        # ethernet phy interface
-        GMII_GTX_CLK=gmii.tx_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,
-        # internal logic 
-        sys_clk=sys_clk,
-        rx_f36_data=stintf.rx_data, 
-        rx_f36_src_rdy=stintf.rx_src_rdy, 
-        rx_f36_dst_rdy=stintf.rx_dst_rdy,
-        tx_f36_data=stintf.tx_data, 
-        tx_f36_src_rdy=stintf.tx_src_rdy, 
-        tx_f36_dst_rdy=stintf.tx_dst_rdy,
-
-        # wishbone interface (device perspective)
-        wb_clk=wb.clk_i,
-        wb_rst=wb.rst_i,
-        wb_stb=wb.stb_i,
-        wb_cyc=wb.cyc_i,
-        wb_ack=wb.ack_o,
-        wb_we=wb.we_i,
-        wb_adr=wb.adr_i,
-        wb_dat_i=wb.dat_i,
-        wb_dat_o=wb.dat_o
-
-        # miim
-        #mdio=mdi, mdc=mdc 
-    )
-
-    return gcosim
-
 #=====================================================================
 def test_simple_gemac(args):
     
 
     # intefaces
     gmii = GMII()
-    stintf = StreamIntf()
-    wb = Wishbone(clock=sys_clk, reset=reset)
+    stif = StreamIntf(eth_clk=clk125, sys_clk=sys_clk)
+    wb = Wishbone(clock=sys_clk, reset=reset, dwidth=32, awidth=8, name='test')
 
-    tbdut = _prep_cosim(args, clk125, reset, gmii, 
-                        sys_clk, stintf, wb)
-    
+    tbdut = prep_cosim(args, clk125, reset, gmii, sys_clk, stif, wb)
+
+    force_error = Signal(bool(0))
+    force_dat_err = Signal(intbv(0)[4:])
+
+    # receive packet interface monitor
+    tbmon = stif.m_rx_packets(sys_clk, reset)
+    txmon = gmii.m_tx_monitor()
+    rxmon = gmii.m_rx_monitor()
     
     def _test():
-        
+        NS = 1 #1000
+
         # note the time scale is 1ns/1ps (1ps)
-        @always(delay(4000))
+        @always(delay(4*NS))
         def tbclk1():
             clk125.next = not clk125
 
-        @always(delay(10000))
+        @always(delay(10*NS))
         def tbclk2():
-            clk_sys.next = not clk_sys
+            sys_clk.next = not sys_clk
 
+        @always_comb
+        def tb_loopback():
+            gmii.rx_dv.next = gmii.tx_en
+            gmii.rx_er.next = gmii.tx_er | force_error
+            gmii.rxd.next = gmii.txd ^ force_dat_err
+            gmii.rx_clk.next = gmii.tx_clk
 
+        def _pause_ticks(N):
+            for _ in range(N):
+                yield clock.posedge
+
+        def bytes_to_32(lst, idx):
+            return concat(intbv(lst[idx+0])[8:],
+                          intbv(lst[idx+1])[8:],
+                          intbv(lst[idx+2])[8:],
+                          intbv(lst[idx+3])[8:])
+
+        pkt_test = Signal(0)
         @instance
         def tbstim():
-            yield delay(13)
+            yield delay(13*NS)
             reset.next = reset.active
-            yield delay(33)
+            yield delay(33*NS)
             reset.next = not reset.active
             yield clock.posedge
 
+            try:
+                print("  ~~~ setup ~~~")
+                # addr 0: misc settings:
+                #  {pause_reqeuest_en, pass_ucast, pass_mcast, pass_bcast,
+                #   pass_pause, pass_all, pause_respect_en} = misc_settings
+                yield wb.write(0x00, int('111101', 2))
+                yield wb.write(0x04, 0xA0B0)      # ucast_addr_h
+                yield wb.write(0x08, 0xC0D0A1B1)  # ucast_addr_l
+                yield wb.write(0x0C, 0x0000)      # mcast_addr_h
+                yield wb.write(0x10, 0x00000000)  # mcast_addr_l
+
+                print("setting mii bits")
+                wb.write(20, 0x08)          # set mdio divider to 8 and nopre to 0
+
+                print("wait")
+                yield _pause_ticks(1000)
+                #for _ in range(1000):
+                #    yield clock.posedge
+
+                print("  ~~~ first packet  ~~~")
+                # this packet is dropped by the filters (verify)
+                pkt_test.next = 1
+                gmii.clear()
+                yield stif.t_tx_packet_sp(0xA0B0C0D0, 10)
+                yield _pause_ticks(100)
+                gmii.dump_monitors()
+                assert len(gmii.txl) >= 10+8+2  # length of epkt, 8 preamble, 4 crc
+                assert bytes_to_32(gmii.txl, 9) == 0xA0B0C0D0
+                # @todo: include generic packet checking, preamble, crc, etc
+
+                print("  ~~~ second packet ~~~")
+                # this packet is dropped by the filters (verify)
+                pkt_test.next = 2
+                gmii.clear()
+                yield stif.t_tx_packet_sp(0xAABBCCDD, 100)
+                yield _pause_ticks(10)
+                # the gmii monitor will capture all bytes (txd), verify
+                # a certain number of bytes recieved
+                assert len(gmii.txl) > 100+8
+                
+                assert gmii.txl[9] 
+
+                yield _pause_ticks(2000)
+                print("  ~~~ third (normal) packet ~~~")
+                pkt_test.next = 3
+                gmii.clear()
+                npkt = 60
+                yield stif.t_tx_packet_from_file_sp(npkt, nwait=7)
+                yield _pause_ticks(2000)
+
+                # @todo: the number of bytes ethernet preamble+header
+                # the ethernet preamble has 8 bytes, the gmii monitors
+                # should contain and extra 8 bytes
+                l1,l2,l3 = len(stif.pkt_mem), len(gmii.txl), len(gmii.rxl)
+                print("  %d, %d, %d" % (l1,l2,l3))
+
+                assert len(gmii.txl) > (npkt+8), "packet not send/recieved"
+                for ii in range(8):
+                    print("  xx  %02X  %02X " % (gmii.txl[ii], gmii.rxl[ii]))
+
+                for ii in range(min((l1,l2,l3,))):
+                    print("  %02X  %02X  %02X " % (stif.pkt_mem[ii],
+                                                   gmii.txl[ii+8],
+                                                   gmii.rxl[ii+8]))
+
+                # some extra ticks at the end
+                print("end wait")
+                yield _pause_ticks(1111)
+                
+
+            except AssertionError, err:
+                print("@E: assertion error occurred")
+                print("    %s" % (str(err)))
+                yield delay(111*NS)
+                raise err
+            except Exception, err:
+                print("@E: assertion error occurred")
+                print("    %s" % (str(err)))
+                yield delay(111*NS)
+                raise err
+
             raise StopSimulation
 
-        return tbclk1, tbclk2, tbstim
+        return tbclk1, tbclk2, tbstim, tb_loopback, tbmon, txmon, rxmon
 
     traceSignals.timescale = '1ps'
     traceSignals.name = 'vcd/_test'
-    fn = trancSignals.name + '.vcd'
+    fn = traceSignals.name + '.vcd'
     if os.path.isfile(fn):
         os.remove(fn)
 

2014/examples/simple_gemac_core/test/vcd/tb_sgem.gtkw

+[*]
+[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
+[*] Mon Jul  7 13:47:13 2014
+[*]
+[dumpfile] "/Users/cfelton/Dropbox/Projects/gsoc_projects/GSoC/2014/examples/simple_gemac_core/test/vcd/_tb_simple_gemac.vcd"
+[dumpfile_mtime] "Mon Jul  7 13:22:24 2014"
+[dumpfile_size] 1876585
+[savefile] "/Users/cfelton/Dropbox/Projects/gsoc_projects/GSoC/2014/examples/simple_gemac_core/test/vcd/tb_sgem.gtkw"
+[timestart] 81989900
+[size] 1272 721
+[pos] -1 -1
+*-16.157663 81230003 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] tb_simple_gemac.
+[treeopen] tb_simple_gemac.DUT.
+[treeopen] tb_simple_gemac.DUT.ll8_to_fifo36.
+[treeopen] tb_simple_gemac.DUT.simple_gemac.
+[sst_width] 198
+[signals_width] 460
+[sst_expanded] 1
+[sst_vpaned_height] 192
+@28
+tb_simple_gemac.reset
+tb_simple_gemac.clk125
+tb_simple_gemac.DUT.sys_clk
+tb_simple_gemac.DUT.tx_ack
+@200
+-
+@28
+tb_simple_gemac.DUT.GMII_GTX_CLK
+tb_simple_gemac.DUT.GMII_TX_EN
+tb_simple_gemac.DUT.GMII_TX_ER
+@22
+tb_simple_gemac.DUT.GMII_TXD[7:0]
+@28
+tb_simple_gemac.GMII_RX_CLK
+tb_simple_gemac.GMII_RX_DV
+tb_simple_gemac.GMII_RX_ER
+@22
+tb_simple_gemac.GMII_RXD[7:0]
+@200
+-
+@28
+tb_simple_gemac.DUT.tx_clk
+@22
+tb_simple_gemac.DUT.tx_data[7:0]
+@28
+tb_simple_gemac.DUT.tx_error
+@200
+-
+@22
+tb_simple_gemac.DUT.tx_f36_data[35:0]
+@28
+tb_simple_gemac.DUT.tx_f36_src_rdy
+tb_simple_gemac.DUT.tx_f36_dst_rdy
+@200
+-
+@c00022
+tb_simple_gemac.rx_f36_data[35:0]
+@28
+(0)tb_simple_gemac.rx_f36_data[35:0]
+(1)tb_simple_gemac.rx_f36_data[35:0]
+(2)tb_simple_gemac.rx_f36_data[35:0]
+(3)tb_simple_gemac.rx_f36_data[35:0]
+(4)tb_simple_gemac.rx_f36_data[35:0]
+(5)tb_simple_gemac.rx_f36_data[35:0]
+(6)tb_simple_gemac.rx_f36_data[35:0]
+(7)tb_simple_gemac.rx_f36_data[35:0]
+(8)tb_simple_gemac.rx_f36_data[35:0]
+(9)tb_simple_gemac.rx_f36_data[35:0]
+(10)tb_simple_gemac.rx_f36_data[35:0]
+(11)tb_simple_gemac.rx_f36_data[35:0]
+(12)tb_simple_gemac.rx_f36_data[35:0]
+(13)tb_simple_gemac.rx_f36_data[35:0]
+(14)tb_simple_gemac.rx_f36_data[35:0]
+(15)tb_simple_gemac.rx_f36_data[35:0]
+(16)tb_simple_gemac.rx_f36_data[35:0]
+(17)tb_simple_gemac.rx_f36_data[35:0]
+(18)tb_simple_gemac.rx_f36_data[35:0]
+(19)tb_simple_gemac.rx_f36_data[35:0]
+(20)tb_simple_gemac.rx_f36_data[35:0]
+(21)tb_simple_gemac.rx_f36_data[35:0]
+(22)tb_simple_gemac.rx_f36_data[35:0]
+(23)tb_simple_gemac.rx_f36_data[35:0]
+(24)tb_simple_gemac.rx_f36_data[35:0]
+(25)tb_simple_gemac.rx_f36_data[35:0]
+(26)tb_simple_gemac.rx_f36_data[35:0]
+(27)tb_simple_gemac.rx_f36_data[35:0]
+(28)tb_simple_gemac.rx_f36_data[35:0]
+(29)tb_simple_gemac.rx_f36_data[35:0]
+(30)tb_simple_gemac.rx_f36_data[35:0]
+(31)tb_simple_gemac.rx_f36_data[35:0]
+(32)tb_simple_gemac.rx_f36_data[35:0]
+(33)tb_simple_gemac.rx_f36_data[35:0]
+(34)tb_simple_gemac.rx_f36_data[35:0]
+(35)tb_simple_gemac.rx_f36_data[35:0]
+@1401200
+-group_end
+@28
+tb_simple_gemac.rx_f36_src_rdy
+tb_simple_gemac.rx_f36_dst_rdy
+@200
+-
+-TX FIFOs
+@28
+tb_simple_gemac.DUT.u_tx_2clk_fifo.wclk
+@29
+tb_simple_gemac.DUT.u_tx_2clk_fifo.src_rdy_i
+@28
+tb_simple_gemac.DUT.u_tx_2clk_fifo.dst_rdy_o
+@22
+tb_simple_gemac.DUT.u_tx_2clk_fifo.datain[35:0]
+@28
+tb_simple_gemac.DUT.u_tx_2clk_fifo.rclk
+tb_simple_gemac.DUT.u_tx_2clk_fifo.src_rdy_o
+tb_simple_gemac.DUT.u_tx_2clk_fifo.dst_rdy_i
+tb_simple_gemac.DUT.u_tx_2clk_fifo.rd
+tb_simple_gemac.DUT.u_tx_2clk_fifo.fbus_rvld
+@22
+tb_simple_gemac.DUT.u_tx_2clk_fifo.dataout_d[35:0]
+tb_simple_gemac.DUT.u_tx_2clk_fifo.dataout[35:0]
+@28
+tb_simple_gemac.DUT.u_tx_2clk_fifo.fbus_empty
+tb_simple_gemac.DUT.u_tx_2clk_fifo.fbus_full
+tb_simple_gemac.DUT.tx_f36_dst_rdy_int1
+@200
+-
+-fifo36_to_ll8
+@28
+tb_simple_gemac.DUT.fifo36_to_ll8.f36_dst_rdy_o
+tb_simple_gemac.DUT.fifo36_to_ll8.advance
+@24
+tb_simple_gemac.DUT.fifo36_to_ll8.state[1:0]
+@28
+tb_simple_gemac.DUT.fifo36_to_ll8.ll_eof
+tb_simple_gemac.DUT.fifo36_to_ll8.f36_eof
+tb_simple_gemac.DUT.fifo36_to_ll8.f36_occ
+@200
+-
+-RX FIFOs
+@28
+tb_simple_gemac.DUT.ll8_to_fifo36.f36_src_rdy_o
+tb_simple_gemac.DUT.ll8_to_fifo36.f36_dst_rdy_i
+tb_simple_gemac.DUT.ll8_to_fifo36.ll_dst_rdy
+tb_simple_gemac.DUT.ll8_to_fifo36.ll_src_rdy
+@200
+-
+@28
+tb_simple_gemac.DUT.u_rx_2clk_fifo.reset
+tb_simple_gemac.DUT.u_rx_2clk_fifo.rclk
+tb_simple_gemac.DUT.u_rx_2clk_fifo.wclk
+@22
+tb_simple_gemac.DUT.rx_f36_data[35:0]
+@28
+tb_simple_gemac.DUT.rx_f36_src_rdy
+tb_simple_gemac.DUT.rx_f36_dst_rdy
+tb_simple_gemac.DUT.rx_f36_src_rdy_int1
+tb_simple_gemac.DUT.rx_f36_dst_rdy_int1
+tb_simple_gemac.DUT.u_rx_2clk_fifo.dst_rdy_o
+tb_simple_gemac.DUT.u_rx_2clk_fifo.fbus_full
+tb_simple_gemac.DUT.u_rx_2clk_fifo.rd
+tb_simple_gemac.DUT.u_rx_2clk_fifo.wr
+@200
+-
+-WISHBONE
+@28
+tb_simple_gemac.DUT.wb_clk
+tb_simple_gemac.DUT.wb_rst
+tb_simple_gemac.DUT.wb_cyc
+tb_simple_gemac.DUT.wb_stb
+tb_simple_gemac.DUT.wb_we
+tb_simple_gemac.DUT.wb_ack
+@22
+tb_simple_gemac.DUT.wb_adr[7:0]
+tb_simple_gemac.DUT.wb_dat_i[31:0]
+tb_simple_gemac.DUT.wb_dat_o[31:0]
+[pattern_trace] 1
+[pattern_trace] 0