data/full_repos/permissive/20726090/hw/vlog/tb/eth_test.v
None: at end of input
1: b'%Error: data/full_repos/permissive/20726090/hw/vlog/tb/eth_test.v:63: Cannot find include file: debug_functions.v\n`include "debug_functions.v" \n         ^~~~~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/20726090/hw/vlog/tb,data/full_repos/permissive/20726090/debug_functions.v\n             data/full_repos/permissive/20726090/hw/vlog/tb,data/full_repos/permissive/20726090/debug_functions.v.v\n             data/full_repos/permissive/20726090/hw/vlog/tb,data/full_repos/permissive/20726090/debug_functions.v.sv\n             debug_functions.v\n             debug_functions.v.v\n             debug_functions.v.sv\n             obj_dir/debug_functions.v\n             obj_dir/debug_functions.v.v\n             obj_dir/debug_functions.v.sv\n%Error: data/full_repos/permissive/20726090/hw/vlog/tb/eth_test.v:64: Cannot find include file: system_functions.v\n`include "system_functions.v" \n         ^~~~~~~~~~~~~~~~~~~~\n%Error: Exiting due to 2 error(s)\n'
module eth_test  
(

inout                       md_io,
input                       mdc_i,


input                       mtx_clk_i,
output reg [3:0]            mtxd_o, 
output reg                  mtxdv_o,
output reg                  mtxerr_o,



input      [3:0]            mrxd_i, 
input                       mrxdv_i
);

`include "debug_functions.v"
`include "system_functions.v"


localparam IDLE = 4'd0;
localparam TX_0 = 4'd1;
localparam TX_1 = 4'd2;
localparam WAIT = 4'd3;
localparam PREA = 4'd4;
localparam PREB = 4'd5;
localparam GAP  = 4'd6;
localparam CRC0 = 4'd7;
localparam CRCN = 4'd8;
localparam POLL = 4'd9;



localparam RX_IDLE = 4'd0;
localparam RX_0    = 4'd1;
localparam RX_1    = 4'd2;
localparam RX_PRE  = 4'd3;
localparam RX_DONE = 4'd4;



localparam MD_REGADDR = 4'd0;
localparam MD_PHYADDR = 4'd1;
localparam MD_WRITE0  = 4'd2;
localparam MD_READ0   = 4'd3;
localparam MD_START1  = 4'd4;
localparam MD_START0  = 4'd5;
localparam MD_IDLE    = 4'd6;
localparam MD_TURN0   = 4'd7;
localparam MD_TURN1   = 4'd8;
localparam MD_RDATA   = 4'd9;
localparam MD_WDATA   = 4'd10;
localparam MD_WXFR    = 4'd11;

localparam MDREAD  = 1'd0;
localparam MDWRITE = 1'd1;



localparam MII_BMCR     = 5'd0;
localparam MII_BMSR     = 5'd1;
localparam MII_CTRL1000 = 5'd9;


reg [7:0]   mem [2**16-1:0];
reg [7:0]   eth [13:0];

reg [7:0]   rxm [2047:0];

reg [15:0]  line_r  = 16'd0;
reg [15:0]  rx_line_r;

reg [3:0]   state_r = IDLE;
reg [3:0]   md_state_r = MD_IDLE;
reg [3:0]   rx_state_r = RX_IDLE;
reg [15:0]  pkt_len_r;
reg [31:0]  wcount_r;
reg [15:0]  pkt_pos_r;
reg [3:0]   pcount_r;

reg         md_op_r = MDREAD;
reg [4:0]   md_count_r;
reg [4:0]   md_phy_addr_r;
reg [4:0]   md_reg_addr_r;
reg [15:0]  md_rdata_r;
reg [15:0]  md_wdata_r;
reg [15:0]  md_bmcr_r = 'd0;
reg [15:0]  md_ctrl1000_r = 16'hffff;
wire        init;
wire [31:0] crc;
wire [3:0]  crc_dinx;                                 
reg  [3:0]  crc_din;
wire        enable;
reg  [3:0]  mrxd_r;

reg  [7:0]  last_pkt_num_r = 'd0;


integer             pkt_to_amber_file;
integer             pkt_to_amber_ack_file;
integer             pkt_from_amber_file;

reg [8*20-1:0]      pkt_to_amber     = "pkt_to_amber.mem";
reg [8*20-1:0]      pkt_to_amber_ack = "pkt_to_amber_ack.txt";
reg [8*20-1:0]      pkt_from_amber   = "pkt_from_amber.mem";

reg     [4*8-1:0]   line;
integer             fgets_return;
integer             pkt_to_amber_address;
reg [7:0]           pkt_to_amber_data;

integer             x;
reg [7:0]           pkt_from_amber_num = 8'd1;




initial
    begin
    pkt_to_amber_ack_file = $fopen(pkt_to_amber_ack, "w");
    $fwrite(pkt_to_amber_ack_file, "0\n");
    $fclose(pkt_to_amber_ack_file);
    end
    
    



always@(posedge mtx_clk_i)
    begin
    case (state_r)
        IDLE:
            begin
            mtxd_o    <= 'd0;
            mtxdv_o   <= 'd0;
            mtxerr_o  <= 'd0;
            wcount_r  <= 'd0;
            
            if (md_bmcr_r[9])
                begin
                wcount_r  <= wcount_r + 1'd1;
                if (wcount_r == 32'd10000)
                    begin
                    state_r   <= POLL;
                    wcount_r  <= 'd0;
                    $display("Start polling for packets to send to amber");
                    end
                end
            end

        
        
        WAIT:
            begin
            wcount_r <= wcount_r + 1'd1;
            if (wcount_r == 32'd100)
                begin
                wcount_r <= 'd0;
                state_r  <= POLL;
                end
            end

        
        POLL:
            begin
            mtxd_o    <= 'd0;
            mtxdv_o   <= 'd0;
            mtxerr_o  <= 'd0;
            
            
            pkt_to_amber_file               = $fopen(pkt_to_amber, "r");            
            fgets_return                    = $fgets(line, pkt_to_amber_file);
            pkt_to_amber_address = 0;
            while (fgets_return)
                begin
                pkt_to_amber_data           = hex_chars_to_8bits (line[23:8]);
                mem[pkt_to_amber_address]   = pkt_to_amber_data[7:0];
                pkt_to_amber_address        = pkt_to_amber_address + 1;
                fgets_return                = $fgets(line, pkt_to_amber_file);                
                end
            $fclose(pkt_to_amber_file);

            
            if (mem[0] != last_pkt_num_r) 
                begin
                state_r         <= PREA;
                pkt_len_r       <= {mem[1], mem[2]} + 16'd14;
                last_pkt_num_r  <= mem[0];
                line_r          <= 'd0;
                pkt_pos_r       <= 'd0;
                pcount_r        <= 'd0;
                wcount_r        <= 'd0;
    
                pkt_to_amber_ack_file = $fopen(pkt_to_amber_ack, "w");
                $fwrite(pkt_to_amber_ack_file, "%d\n", mem[0]);
                $fclose(pkt_to_amber_ack_file);
                end
            else begin
                state_r   <= WAIT;
                end
                
            end
                        
        
        
        PREA:
            begin
            mtxd_o    <= 4'b0101;
            mtxdv_o   <= 1'd1;
            pcount_r  <= pcount_r + 1'd1;
            if (pcount_r == 4'd6)
                begin
                pcount_r  <= 'd0;
                state_r   <= PREB;            
                end
            end
            
            
        PREB:
            begin
            mtxd_o    <= 4'b1101;
            mtxdv_o   <= 1'd1;
            state_r   <= TX_0;
            
            print_pkt(1'd1, line_r);  
            end 
            
                           
        TX_0:
            begin
            mtxd_o    <= mem[line_r+3][3:0];
            mtxdv_o   <= 1'd1;
            state_r   <= TX_1;
            end
            
            
        TX_1:
            begin
            mtxd_o    <= mem[line_r+3][7:4];
            mtxdv_o   <= 1'd1;
            line_r    <= line_r + 1'd1;
            
            if (pkt_pos_r + 1'd1 == pkt_len_r)
                state_r     <= CRC0;
            else
                begin
                state_r     <= TX_0;
                pkt_pos_r   <= pkt_pos_r + 1'd1;
                end
            end

                        
        CRC0:
            begin
            mtxd_o    <= {~crc[28], ~crc[29], ~crc[30], ~crc[31]};
            mtxdv_o   <= 1'd1;
            state_r   <= POLL;
            end
            
    endcase
    end
            


assign init    = state_r == PREB;
assign enable  = state_r != CRC0;

always @*
    begin
        crc_din = state_r == TX_0 ? mem[line_r+3][3:0] : 
                  state_r == TX_1 ? mem[line_r+3][7:4] :
                                   32'd0               ;
    end
    
                                       
assign crc_dinx = {crc_din[0], crc_din[1], crc_din[2], crc_din[3]};



eth_crc eth_crc (
    .Clk        ( mtx_clk_i ),
    .Reset      ( 1'd0      ),
    .Data       ( crc_dinx  ),
    .Enable     ( enable    ),
    .Initialize ( init      ),

    .Crc        ( crc       ),
    .CrcError   (           )
);





always@(posedge mtx_clk_i)
    begin
    case (rx_state_r)
        RX_IDLE:
            begin  
            rx_line_r  <= 'd0;       
            if (mrxdv_i)
                begin
                rx_state_r   <= RX_PRE;
                end
            end
                       
        RX_PRE:
            begin
            if (mrxd_i == 4'hd)
                rx_state_r   <= RX_0;
            end
                               
        RX_0:
            begin
            mrxd_r <= mrxd_i;
            
            if (mrxdv_i)
                rx_state_r     <= RX_1;
            else
                rx_state_r     <= RX_DONE;
            end
            
            
        RX_1:
            begin
            rxm[rx_line_r]      <= {mrxd_i, mrxd_r};
            rx_line_r           <= rx_line_r + 1'd1;
            
            if (mrxdv_i)
                rx_state_r     <= RX_0;
            else
                rx_state_r     <= RX_DONE;
            end


        RX_DONE: 
            begin
            print_pkt(1'd0, 16'd0);  
            rx_state_r     <= RX_IDLE;
            
                
            pkt_from_amber_file     = $fopen(pkt_from_amber, "w");
            $fwrite(pkt_from_amber_file, "%02h\n", pkt_from_amber_num);
            
            for (x=0;x<rx_line_r;x=x+1)
                $fwrite(pkt_from_amber_file, "%02h\n", rxm[x]);
            $fclose(pkt_from_amber_file);
            
            
            if (pkt_from_amber_num == 8'd255)
                pkt_from_amber_num  <= 8'd1; 
            else
                pkt_from_amber_num  <=  pkt_from_amber_num + 1'd1; 
            end
            
            
    endcase
    end







always@(posedge mdc_i)
    begin
    case (md_state_r)
    
        MD_IDLE:
            begin
            md_count_r <= 'd0;
            if (md_io == 1'd0)
                md_state_r   <= MD_START0;
            end
            
            
        MD_START0:
            begin
            if (md_io == 1'd1)
                md_state_r   <= MD_START1;
            else
                md_state_r   <= MD_IDLE;
            end
            
            
        MD_START1:
            begin
            if (md_io == 1'd1)
                md_state_r  <= MD_READ0;
            else
                md_state_r  <= MD_WRITE0;
            end
            
            
       MD_READ0:
            begin
            if (md_io == 1'd0)
                begin
                md_state_r  <= MD_PHYADDR;
                md_op_r     <= MDREAD;
                end
            else
                md_state_r  <= MD_IDLE;
            end 
            
            
       MD_WRITE0:
            begin
            if (md_io == 1'd1)
                begin
                md_state_r  <= MD_PHYADDR;
                md_op_r     <= MDWRITE;
                end
            else
                md_state_r  <= MD_IDLE;
            end 
            
        MD_PHYADDR:
            begin
            md_count_r      <= md_count_r + 1'd1;
            md_phy_addr_r   <= {md_phy_addr_r[3:0], md_io};
            
            if (md_count_r == 5'd4)
                begin
                md_state_r  <= MD_REGADDR;
                md_count_r  <= 'd0;                
                end
            end
            
        MD_REGADDR:
            begin
            md_count_r      <= md_count_r + 1'd1;
            md_reg_addr_r   <= {md_reg_addr_r[3:0], md_io};
            
            if (md_count_r == 5'd4)
                begin
                md_count_r  <= 'd0;                
                md_state_r  <= MD_TURN0;
                end
            end


        MD_TURN0:
            md_state_r  <= MD_TURN1;

        MD_TURN1:
            begin
            if (md_op_r == MDREAD)
                md_state_r  <= MD_RDATA;
            else    
                md_state_r  <= MD_WDATA;
                
            case (md_reg_addr_r)
                MII_BMCR        : md_rdata_r <= md_bmcr_r;
                MII_BMSR        : md_rdata_r <= 16'hfe04;
                MII_CTRL1000    : md_rdata_r <= md_ctrl1000_r;
                default         : md_rdata_r <= 'd0;   
            endcase
            end
            
            
        MD_RDATA:
            begin
            md_count_r  <= md_count_r + 1'd1;
            md_rdata_r  <= {md_rdata_r[14:0], 1'd0};
            
            if (md_count_r == 5'd15)
                md_state_r  <= MD_IDLE;
            
            end


        MD_WDATA:
            begin
            md_count_r  <= md_count_r + 1'd1;
            md_wdata_r  <= {md_wdata_r[14:0], md_io};
            
            if (md_count_r == 5'd15)
                begin
                md_state_r  <= MD_WXFR;
                md_count_r  <= 'd0;                
                end
            end


        MD_WXFR:
            begin
            case (md_reg_addr_r)
                MII_BMCR        : md_bmcr_r     <= md_wdata_r;
                MII_CTRL1000    : md_ctrl1000_r <= md_wdata_r;
            endcase
            md_state_r  <= MD_IDLE;
            end
            
            
    endcase
    end


assign md_io = md_state_r == MD_RDATA ? md_rdata_r[15] : 1'bz;



task print_pkt;
input        tx;
input [31:0] start;
reg   [15:0] eth_type;
reg   [7:0]  proto;
reg   [31:0] frame;
reg   [3:0]  ip_hdr_len;
reg   [15:0] ip_len;
reg   [3:0]  tcp_hdr_len;
reg   [15:0] tcp_bdy_len;
reg   [7:0]  tmp;
reg   [15:0] arp_op;

integer      i;
begin
    frame = start;
    
    if (tx) $write("%6d pkt to   amber ", tb.clk_count);
    else    $write("%6d pkt from amber ", tb.clk_count);
    
    $display("mac-dst %h:%h:%h:%h:%h:%h, mac-src %h:%h:%h:%h:%h:%h, type %h%h", 
        rmem(tx,frame+0), rmem(tx,frame+1),rmem(tx,frame+2),rmem(tx,frame+3),rmem(tx,frame+4),rmem(tx,frame+5),
        rmem(tx,frame+6), rmem(tx,frame+7),rmem(tx,frame+8),rmem(tx,frame+9),rmem(tx,frame+10),rmem(tx,frame+11),
        rmem(tx,frame+12),rmem(tx,frame+13));
        
    eth_type = {rmem(tx,frame+12),rmem(tx,frame+13)};

    if (eth_type == 16'h0806)
        begin
        frame       = frame + 14;
        arp_op      = rmem(tx,frame+6) << 8 | rmem(tx,frame+7);
        
        $write("ARP operation %0d", arp_op);
      
        if (arp_op == 16'd1)
            $write(" look for ip %0d.%0d.%0d.%0d", 
                rmem(tx,frame+24), rmem(tx,frame+25),rmem(tx,frame+26),rmem(tx,frame+27));  
        $write("\n");      
        end
    
    if (eth_type == 16'h0800)
        begin
        frame       = frame + 14;
        proto       = rmem(tx,frame+9);
        tmp         = rmem(tx,frame+0);
        ip_hdr_len  = tmp[3:0];
        ip_len      = {rmem(tx,frame+2), rmem(tx,frame+3)};
        
        $display("   ip-dst %0d.%0d.%0d.%0d, ip-src %0d.%0d.%0d.%0d, proto %0d, ip_len %0d, ihl %0d", 
            rmem(tx,frame+16), rmem(tx,frame+17),rmem(tx,frame+18),rmem(tx,frame+19),
            rmem(tx,frame+12), rmem(tx,frame+13),rmem(tx,frame+14),rmem(tx,frame+15), 
            proto, ip_len, ip_hdr_len*4);
        
        if (proto == 8'd6)
            begin
            frame       = frame + ip_hdr_len*4;
            tmp         = rmem(tx,frame+12);
            tcp_hdr_len = tmp[7:4];
            tcp_bdy_len = ip_len - ({ip_hdr_len,2'd0} + {tcp_hdr_len,2'd0});
            
            $display("   tcp-dst %0d, tcp-src %0d, tcp hdr len %0d, tcp bdy len %0d", 
                {rmem(tx,frame+2), rmem(tx,frame+3)},
                {rmem(tx,frame+0), rmem(tx,frame+1)}, tcp_hdr_len*4, tcp_bdy_len);
            $display("   tcp-seq %0d, tcp-ack %0d", 
                {rmem(tx,frame+4), rmem(tx,frame+5), rmem(tx,frame+6), rmem(tx,frame+7)},
                {rmem(tx,frame+8), rmem(tx,frame+9), rmem(tx,frame+10), rmem(tx,frame+11)});
                
            if (tcp_bdy_len != 16'd0)
                begin
                for (i=0;i<tcp_bdy_len;i=i+1)
                    if ((rmem(tx,frame+tcp_hdr_len*4+i) > 31 && rmem(tx,frame+tcp_hdr_len*4+i) < 128) ||
                        (rmem(tx,frame+tcp_hdr_len*4+i) == "\n"))
                        $write("%c",  rmem(tx,frame+tcp_hdr_len*4+i));
                end
                
            end
        end
    $display("----");
end
endtask


function [7:0] rmem;
input        tx;
input [31:0] addr;
begin
    if (tx)
        rmem = mem[addr+3];
    else
        rmem = rxm[addr];
end
endfunction


wire [8*6-1:0] XSTATE = 
    state_r == IDLE ? "IDLE"    :
    state_r == WAIT ? "WAIT"    :
    state_r == TX_0 ? "TX_0"    :
    state_r == TX_1 ? "TX_1"    :
    state_r == PREA ? "PREA"    :
    state_r == PREB ? "PREB"    :
    state_r == GAP  ? "GAP"     :
    state_r == CRC0 ? "CRC0"    :
    state_r == CRCN ? "CRCN"    :
    state_r == POLL ? "POLL"    :
                      "UNKNOWN" ;

wire [8*12-1:0] XRXSTATE = 
    state_r == RX_IDLE  ? "RX_IDLE" :
    state_r == RX_0     ? "RX_0"    :
    state_r == RX_1     ? "RX_1"    :
    state_r == RX_PRE   ? "RX_PRE"  :
    state_r == RX_DONE  ? "RX_DONE" :
                          "UNKNOWN" ;

wire [8*12-1:0] XMDSTATE =
    md_state_r == MD_WXFR    ?  "MD_WXFR"    :
    md_state_r == MD_WDATA   ?  "MD_WDATA"   :
    md_state_r == MD_RDATA   ?  "MD_RDATA"   :
    md_state_r == MD_TURN1   ?  "MD_TURN1"   :
    md_state_r == MD_TURN0   ?  "MD_TURN0"   :
    md_state_r == MD_REGADDR ?  "MD_REGADDR" :
    md_state_r == MD_PHYADDR ?  "MD_PHYADDR" :
    md_state_r == MD_WRITE0  ?  "MD_WRITE0"  :
    md_state_r == MD_READ0   ?  "MD_READ0"   :
    md_state_r == MD_START1  ?  "MD_START1"  :
    md_state_r == MD_START0  ?  "MD_START0"  :
    md_state_r == MD_IDLE    ?  "MD_IDLE"    :
                                "UNKNOWN"    ;

endmodule
module eth_test  
(

inout                       md_io,
input                       mdc_i,


input                       mtx_clk_i,
output reg [3:0]            mtxd_o, 
output reg                  mtxdv_o,
output reg                  mtxerr_o,



input      [3:0]            mrxd_i, 
input                       mrxdv_i
);


`include "debug_functions.v"
`include "system_functions.v"


localparam IDLE = 4'd0;
localparam TX_0 = 4'd1;
localparam TX_1 = 4'd2;
localparam WAIT = 4'd3;
localparam PREA = 4'd4;
localparam PREB = 4'd5;
localparam GAP  = 4'd6;
localparam CRC0 = 4'd7;
localparam CRCN = 4'd8;
localparam POLL = 4'd9;



localparam RX_IDLE = 4'd0;
localparam RX_0    = 4'd1;
localparam RX_1    = 4'd2;
localparam RX_PRE  = 4'd3;
localparam RX_DONE = 4'd4;



localparam MD_REGADDR = 4'd0;
localparam MD_PHYADDR = 4'd1;
localparam MD_WRITE0  = 4'd2;
localparam MD_READ0   = 4'd3;
localparam MD_START1  = 4'd4;
localparam MD_START0  = 4'd5;
localparam MD_IDLE    = 4'd6;
localparam MD_TURN0   = 4'd7;
localparam MD_TURN1   = 4'd8;
localparam MD_RDATA   = 4'd9;
localparam MD_WDATA   = 4'd10;
localparam MD_WXFR    = 4'd11;

localparam MDREAD  = 1'd0;
localparam MDWRITE = 1'd1;



localparam MII_BMCR     = 5'd0;
localparam MII_BMSR     = 5'd1;
localparam MII_CTRL1000 = 5'd9;


reg [7:0]   mem [2**16-1:0];
reg [7:0]   eth [13:0];

reg [7:0]   rxm [2047:0];

reg [15:0]  line_r  = 16'd0;
reg [15:0]  rx_line_r;

reg [3:0]   state_r = IDLE;
reg [3:0]   md_state_r = MD_IDLE;
reg [3:0]   rx_state_r = RX_IDLE;
reg [15:0]  pkt_len_r;
reg [31:0]  wcount_r;
reg [15:0]  pkt_pos_r;
reg [3:0]   pcount_r;

reg         md_op_r = MDREAD;
reg [4:0]   md_count_r;
reg [4:0]   md_phy_addr_r;
reg [4:0]   md_reg_addr_r;
reg [15:0]  md_rdata_r;
reg [15:0]  md_wdata_r;
reg [15:0]  md_bmcr_r = 'd0;
reg [15:0]  md_ctrl1000_r = 16'hffff;
wire        init;
wire [31:0] crc;
wire [3:0]  crc_dinx;                                 
reg  [3:0]  crc_din;
wire        enable;
reg  [3:0]  mrxd_r;

reg  [7:0]  last_pkt_num_r = 'd0;


integer             pkt_to_amber_file;
integer             pkt_to_amber_ack_file;
integer             pkt_from_amber_file;

reg [8*20-1:0]      pkt_to_amber     = "pkt_to_amber.mem";
reg [8*20-1:0]      pkt_to_amber_ack = "pkt_to_amber_ack.txt";
reg [8*20-1:0]      pkt_from_amber   = "pkt_from_amber.mem";

reg     [4*8-1:0]   line;
integer             fgets_return;
integer             pkt_to_amber_address;
reg [7:0]           pkt_to_amber_data;

integer             x;
reg [7:0]           pkt_from_amber_num = 8'd1;




initial
    begin
    pkt_to_amber_ack_file = $fopen(pkt_to_amber_ack, "w");
    $fwrite(pkt_to_amber_ack_file, "0\n");
    $fclose(pkt_to_amber_ack_file);
    end
    
    



always@(posedge mtx_clk_i)
    begin
    case (state_r)
        IDLE:
            begin
            mtxd_o    <= 'd0;
            mtxdv_o   <= 'd0;
            mtxerr_o  <= 'd0;
            wcount_r  <= 'd0;
            
            if (md_bmcr_r[9])
                begin
                wcount_r  <= wcount_r + 1'd1;
                if (wcount_r == 32'd10000)
                    begin
                    state_r   <= POLL;
                    wcount_r  <= 'd0;
                    $display("Start polling for packets to send to amber");
                    end
                end
            end

        
        
        WAIT:
            begin
            wcount_r <= wcount_r + 1'd1;
            if (wcount_r == 32'd100)
                begin
                wcount_r <= 'd0;
                state_r  <= POLL;
                end
            end

        
        POLL:
            begin
            mtxd_o    <= 'd0;
            mtxdv_o   <= 'd0;
            mtxerr_o  <= 'd0;
            
            
            pkt_to_amber_file               = $fopen(pkt_to_amber, "r");            
            fgets_return                    = $fgets(line, pkt_to_amber_file);
            pkt_to_amber_address = 0;
            while (fgets_return)
                begin
                pkt_to_amber_data           = hex_chars_to_8bits (line[23:8]);
                mem[pkt_to_amber_address]   = pkt_to_amber_data[7:0];
                pkt_to_amber_address        = pkt_to_amber_address + 1;
                fgets_return                = $fgets(line, pkt_to_amber_file);                
                end
            $fclose(pkt_to_amber_file);

            
            if (mem[0] != last_pkt_num_r) 
                begin
                state_r         <= PREA;
                pkt_len_r       <= {mem[1], mem[2]} + 16'd14;
                last_pkt_num_r  <= mem[0];
                line_r          <= 'd0;
                pkt_pos_r       <= 'd0;
                pcount_r        <= 'd0;
                wcount_r        <= 'd0;
    
                pkt_to_amber_ack_file = $fopen(pkt_to_amber_ack, "w");
                $fwrite(pkt_to_amber_ack_file, "%d\n", mem[0]);
                $fclose(pkt_to_amber_ack_file);
                end
            else begin
                state_r   <= WAIT;
                end
                
            end
                        
        
        
        PREA:
            begin
            mtxd_o    <= 4'b0101;
            mtxdv_o   <= 1'd1;
            pcount_r  <= pcount_r + 1'd1;
            if (pcount_r == 4'd6)
                begin
                pcount_r  <= 'd0;
                state_r   <= PREB;            
                end
            end
            
            
        PREB:
            begin
            mtxd_o    <= 4'b1101;
            mtxdv_o   <= 1'd1;
            state_r   <= TX_0;
            
            print_pkt(1'd1, line_r);  
            end 
            
                           
        TX_0:
            begin
            mtxd_o    <= mem[line_r+3][3:0];
            mtxdv_o   <= 1'd1;
            state_r   <= TX_1;
            end
            
            
        TX_1:
            begin
            mtxd_o    <= mem[line_r+3][7:4];
            mtxdv_o   <= 1'd1;
            line_r    <= line_r + 1'd1;
            
            if (pkt_pos_r + 1'd1 == pkt_len_r)
                state_r     <= CRC0;
            else
                begin
                state_r     <= TX_0;
                pkt_pos_r   <= pkt_pos_r + 1'd1;
                end
            end

                        
        CRC0:
            begin
            mtxd_o    <= {~crc[28], ~crc[29], ~crc[30], ~crc[31]};
            mtxdv_o   <= 1'd1;
            state_r   <= POLL;
            end
            
    endcase
    end
            


assign init    = state_r == PREB;
assign enable  = state_r != CRC0;

always @*
    begin
        crc_din = state_r == TX_0 ? mem[line_r+3][3:0] : 
                  state_r == TX_1 ? mem[line_r+3][7:4] :
                                   32'd0               ;
    end
    
                                       
assign crc_dinx = {crc_din[0], crc_din[1], crc_din[2], crc_din[3]};



eth_crc eth_crc (
    .Clk        ( mtx_clk_i ),
    .Reset      ( 1'd0      ),
    .Data       ( crc_dinx  ),
    .Enable     ( enable    ),
    .Initialize ( init      ),

    .Crc        ( crc       ),
    .CrcError   (           )
);





always@(posedge mtx_clk_i)
    begin
    case (rx_state_r)
        RX_IDLE:
            begin  
            rx_line_r  <= 'd0;       
            if (mrxdv_i)
                begin
                rx_state_r   <= RX_PRE;
                end
            end
                       
        RX_PRE:
            begin
            if (mrxd_i == 4'hd)
                rx_state_r   <= RX_0;
            end
                               
        RX_0:
            begin
            mrxd_r <= mrxd_i;
            
            if (mrxdv_i)
                rx_state_r     <= RX_1;
            else
                rx_state_r     <= RX_DONE;
            end
            
            
        RX_1:
            begin
            rxm[rx_line_r]      <= {mrxd_i, mrxd_r};
            rx_line_r           <= rx_line_r + 1'd1;
            
            if (mrxdv_i)
                rx_state_r     <= RX_0;
            else
                rx_state_r     <= RX_DONE;
            end


        RX_DONE: 
            begin
            print_pkt(1'd0, 16'd0);  
            rx_state_r     <= RX_IDLE;
            
                
            pkt_from_amber_file     = $fopen(pkt_from_amber, "w");
            $fwrite(pkt_from_amber_file, "%02h\n", pkt_from_amber_num);
            
            for (x=0;x<rx_line_r;x=x+1)
                $fwrite(pkt_from_amber_file, "%02h\n", rxm[x]);
            $fclose(pkt_from_amber_file);
            
            
            if (pkt_from_amber_num == 8'd255)
                pkt_from_amber_num  <= 8'd1; 
            else
                pkt_from_amber_num  <=  pkt_from_amber_num + 1'd1; 
            end
            
            
    endcase
    end







always@(posedge mdc_i)
    begin
    case (md_state_r)
    
        MD_IDLE:
            begin
            md_count_r <= 'd0;
            if (md_io == 1'd0)
                md_state_r   <= MD_START0;
            end
            
            
        MD_START0:
            begin
            if (md_io == 1'd1)
                md_state_r   <= MD_START1;
            else
                md_state_r   <= MD_IDLE;
            end
            
            
        MD_START1:
            begin
            if (md_io == 1'd1)
                md_state_r  <= MD_READ0;
            else
                md_state_r  <= MD_WRITE0;
            end
            
            
       MD_READ0:
            begin
            if (md_io == 1'd0)
                begin
                md_state_r  <= MD_PHYADDR;
                md_op_r     <= MDREAD;
                end
            else
                md_state_r  <= MD_IDLE;
            end 
            
            
       MD_WRITE0:
            begin
            if (md_io == 1'd1)
                begin
                md_state_r  <= MD_PHYADDR;
                md_op_r     <= MDWRITE;
                end
            else
                md_state_r  <= MD_IDLE;
            end 
            
        MD_PHYADDR:
            begin
            md_count_r      <= md_count_r + 1'd1;
            md_phy_addr_r   <= {md_phy_addr_r[3:0], md_io};
            
            if (md_count_r == 5'd4)
                begin
                md_state_r  <= MD_REGADDR;
                md_count_r  <= 'd0;                
                end
            end
            
        MD_REGADDR:
            begin
            md_count_r      <= md_count_r + 1'd1;
            md_reg_addr_r   <= {md_reg_addr_r[3:0], md_io};
            
            if (md_count_r == 5'd4)
                begin
                md_count_r  <= 'd0;                
                md_state_r  <= MD_TURN0;
                end
            end


        MD_TURN0:
            md_state_r  <= MD_TURN1;

        MD_TURN1:
            begin
            if (md_op_r == MDREAD)
                md_state_r  <= MD_RDATA;
            else    
                md_state_r  <= MD_WDATA;
                
            case (md_reg_addr_r)
                MII_BMCR        : md_rdata_r <= md_bmcr_r;
                MII_BMSR        : md_rdata_r <= 16'hfe04;
                MII_CTRL1000    : md_rdata_r <= md_ctrl1000_r;
                default         : md_rdata_r <= 'd0;   
            endcase
            end
            
            
        MD_RDATA:
            begin
            md_count_r  <= md_count_r + 1'd1;
            md_rdata_r  <= {md_rdata_r[14:0], 1'd0};
            
            if (md_count_r == 5'd15)
                md_state_r  <= MD_IDLE;
            
            end


        MD_WDATA:
            begin
            md_count_r  <= md_count_r + 1'd1;
            md_wdata_r  <= {md_wdata_r[14:0], md_io};
            
            if (md_count_r == 5'd15)
                begin
                md_state_r  <= MD_WXFR;
                md_count_r  <= 'd0;                
                end
            end


        MD_WXFR:
            begin
            case (md_reg_addr_r)
                MII_BMCR        : md_bmcr_r     <= md_wdata_r;
                MII_CTRL1000    : md_ctrl1000_r <= md_wdata_r;
            endcase
            md_state_r  <= MD_IDLE;
            end
            
            
    endcase
    end


assign md_io = md_state_r == MD_RDATA ? md_rdata_r[15] : 1'bz;



task print_pkt;
input        tx;
input [31:0] start;
reg   [15:0] eth_type;
reg   [7:0]  proto;
reg   [31:0] frame;
reg   [3:0]  ip_hdr_len;
reg   [15:0] ip_len;
reg   [3:0]  tcp_hdr_len;
reg   [15:0] tcp_bdy_len;
reg   [7:0]  tmp;
reg   [15:0] arp_op;

integer      i;
begin
    frame = start;
    
    if (tx) $write("%6d pkt to   amber ", tb.clk_count);
    else    $write("%6d pkt from amber ", tb.clk_count);
    
    $display("mac-dst %h:%h:%h:%h:%h:%h, mac-src %h:%h:%h:%h:%h:%h, type %h%h", 
        rmem(tx,frame+0), rmem(tx,frame+1),rmem(tx,frame+2),rmem(tx,frame+3),rmem(tx,frame+4),rmem(tx,frame+5),
        rmem(tx,frame+6), rmem(tx,frame+7),rmem(tx,frame+8),rmem(tx,frame+9),rmem(tx,frame+10),rmem(tx,frame+11),
        rmem(tx,frame+12),rmem(tx,frame+13));
        
    eth_type = {rmem(tx,frame+12),rmem(tx,frame+13)};

    if (eth_type == 16'h0806)
        begin
        frame       = frame + 14;
        arp_op      = rmem(tx,frame+6) << 8 | rmem(tx,frame+7);
        
        $write("ARP operation %0d", arp_op);
      
        if (arp_op == 16'd1)
            $write(" look for ip %0d.%0d.%0d.%0d", 
                rmem(tx,frame+24), rmem(tx,frame+25),rmem(tx,frame+26),rmem(tx,frame+27));  
        $write("\n");      
        end
    
    if (eth_type == 16'h0800)
        begin
        frame       = frame + 14;
        proto       = rmem(tx,frame+9);
        tmp         = rmem(tx,frame+0);
        ip_hdr_len  = tmp[3:0];
        ip_len      = {rmem(tx,frame+2), rmem(tx,frame+3)};
        
        $display("   ip-dst %0d.%0d.%0d.%0d, ip-src %0d.%0d.%0d.%0d, proto %0d, ip_len %0d, ihl %0d", 
            rmem(tx,frame+16), rmem(tx,frame+17),rmem(tx,frame+18),rmem(tx,frame+19),
            rmem(tx,frame+12), rmem(tx,frame+13),rmem(tx,frame+14),rmem(tx,frame+15), 
            proto, ip_len, ip_hdr_len*4);
        
        if (proto == 8'd6)
            begin
            frame       = frame + ip_hdr_len*4;
            tmp         = rmem(tx,frame+12);
            tcp_hdr_len = tmp[7:4];
            tcp_bdy_len = ip_len - ({ip_hdr_len,2'd0} + {tcp_hdr_len,2'd0});
            
            $display("   tcp-dst %0d, tcp-src %0d, tcp hdr len %0d, tcp bdy len %0d", 
                {rmem(tx,frame+2), rmem(tx,frame+3)},
                {rmem(tx,frame+0), rmem(tx,frame+1)}, tcp_hdr_len*4, tcp_bdy_len);
            $display("   tcp-seq %0d, tcp-ack %0d", 
                {rmem(tx,frame+4), rmem(tx,frame+5), rmem(tx,frame+6), rmem(tx,frame+7)},
                {rmem(tx,frame+8), rmem(tx,frame+9), rmem(tx,frame+10), rmem(tx,frame+11)});
                
            if (tcp_bdy_len != 16'd0)
                begin
                for (i=0;i<tcp_bdy_len;i=i+1)
                    if ((rmem(tx,frame+tcp_hdr_len*4+i) > 31 && rmem(tx,frame+tcp_hdr_len*4+i) < 128) ||
                        (rmem(tx,frame+tcp_hdr_len*4+i) == "\n"))
                        $write("%c",  rmem(tx,frame+tcp_hdr_len*4+i));
                end
                
            end
        end
    $display("----");
end
endtask


function [7:0] rmem;
input        tx;
input [31:0] addr;
begin
    if (tx)
        rmem = mem[addr+3];
    else
        rmem = rxm[addr];
end
endfunction


wire [8*6-1:0] XSTATE = 
    state_r == IDLE ? "IDLE"    :
    state_r == WAIT ? "WAIT"    :
    state_r == TX_0 ? "TX_0"    :
    state_r == TX_1 ? "TX_1"    :
    state_r == PREA ? "PREA"    :
    state_r == PREB ? "PREB"    :
    state_r == GAP  ? "GAP"     :
    state_r == CRC0 ? "CRC0"    :
    state_r == CRCN ? "CRCN"    :
    state_r == POLL ? "POLL"    :
                      "UNKNOWN" ;

wire [8*12-1:0] XRXSTATE = 
    state_r == RX_IDLE  ? "RX_IDLE" :
    state_r == RX_0     ? "RX_0"    :
    state_r == RX_1     ? "RX_1"    :
    state_r == RX_PRE   ? "RX_PRE"  :
    state_r == RX_DONE  ? "RX_DONE" :
                          "UNKNOWN" ;

wire [8*12-1:0] XMDSTATE =
    md_state_r == MD_WXFR    ?  "MD_WXFR"    :
    md_state_r == MD_WDATA   ?  "MD_WDATA"   :
    md_state_r == MD_RDATA   ?  "MD_RDATA"   :
    md_state_r == MD_TURN1   ?  "MD_TURN1"   :
    md_state_r == MD_TURN0   ?  "MD_TURN0"   :
    md_state_r == MD_REGADDR ?  "MD_REGADDR" :
    md_state_r == MD_PHYADDR ?  "MD_PHYADDR" :
    md_state_r == MD_WRITE0  ?  "MD_WRITE0"  :
    md_state_r == MD_READ0   ?  "MD_READ0"   :
    md_state_r == MD_START1  ?  "MD_START1"  :
    md_state_r == MD_START0  ?  "MD_START0"  :
    md_state_r == MD_IDLE    ?  "MD_IDLE"    :
                                "UNKNOWN"    ;

endmodule