OpenCores
URL https://opencores.org/ocsvn/amber/amber/trunk

Subversion Repositories amber

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /amber/trunk/hw/vlog/tb
    from Rev 49 to Rev 61
    Reverse comparison

Rev 49 → Rev 61

/debug_functions.v
56,6 → 56,15
endfunction
 
 
function [7:0] hex_chars_to_8bits;
input [8*2-1:0] hex_chars;
begin
hex_chars_to_8bits[ 7: 4] = hex_chars_to_4bits (hex_chars[2*8-1:1*8]);
hex_chars_to_8bits[ 3: 0] = hex_chars_to_4bits (hex_chars[1*8-1: 0]);
end
endfunction
 
 
function [3:0] hex_chars_to_4bits;
input [7:0] hex_chars;
begin
/eth_test.v
0,0 → 1,683
//////////////////////////////////////////////////////////////////
// //
// Top-level module instantiating the entire Amber 2 system. //
// //
// This file is part of the Amber project //
// http://www.opencores.org/project,amber //
// //
// Description //
// This is the highest level synthesizable module in the //
// project. The ports in this module represent pins on the //
// FPGA. //
// //
// Author(s): //
// - Conor Santifort, csantifort.amber@gmail.com //
// //
//////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2012 Authors and OPENCORES.ORG //
// //
// This source file may be used and distributed without //
// restriction provided that this copyright statement is not //
// removed from the file and that any derivative work contains //
// the original copyright notice and the associated disclaimer. //
// //
// This source file is free software; you can redistribute it //
// and/or modify it under the terms of the GNU Lesser General //
// Public License as published by the Free Software Foundation; //
// either version 2.1 of the License, or (at your option) any //
// later version. //
// //
// This source is distributed in the hope that it will be //
// useful, but WITHOUT ANY WARRANTY; without even the implied //
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
// PURPOSE. See the GNU Lesser General Public License for more //
// details. //
// //
// You should have received a copy of the GNU Lesser General //
// Public License along with this source; if not, download it //
// from http://www.opencores.org/lgpl.shtml //
// //
//////////////////////////////////////////////////////////////////
`timescale 1 ps / 1 ps
 
 
module eth_test
(
// MD interface - serial configuration of PHY
inout md_io,
input mdc_i,
 
// MAC interface - packet to DUT
input mtx_clk_i,
output reg [3:0] mtxd_o,
output reg mtxdv_o,
output reg mtxerr_o,
 
 
// MAC interface - packet from DUT
input [3:0] mrxd_i,
input mrxdv_i
);
 
`include "debug_functions.v"
`include "system_functions.v"
 
// mxt state machine
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;
 
 
// rx state machine
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;
 
 
// md state machine
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;
 
 
// MD register addresses
localparam MII_BMCR = 5'd0; /* Basic mode control register */
localparam MII_BMSR = 5'd1; /* Basic mode status register */
localparam MII_CTRL1000 = 5'd9; /* 1000BASE-T control */
 
 
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;
 
 
// initializwe the ack file to 0
// this allows sim_socket to write the first packet
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
// ============================
// packet tx state machine
// ============================
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]) // autoneg bit set by software
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: // scan for new packets
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: // Preamble
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: // low 4 bits
begin
mtxd_o <= mem[line_r+3][3:0];
mtxdv_o <= 1'd1;
state_r <= TX_1;
end
TX_1: // high 4 bits
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]};
 
 
// Gen CRC, using the EthMac CRC generator
eth_crc eth_crc (
.Clk ( mtx_clk_i ),
.Reset ( 1'd0 ),
.Data ( crc_dinx ),
.Enable ( enable ),
.Initialize ( init ),
 
.Crc ( crc ),
.CrcError ( )
);
 
 
// ============================
// packet rx state machine
// ============================
always@(posedge mtx_clk_i)
begin
case (rx_state_r)
RX_IDLE:
begin
rx_line_r <= 'd0;
if (mrxdv_i) // autoneg bit set by software
begin
rx_state_r <= RX_PRE;
end
end
RX_PRE:
begin
if (mrxd_i == 4'hd)
rx_state_r <= RX_0;
end
RX_0: // low 4 bits
begin
mrxd_r <= mrxd_i;
if (mrxdv_i)
rx_state_r <= RX_1;
else
rx_state_r <= RX_DONE;
end
RX_1: // high 4 bits
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
 
 
 
 
// ============================
// management data state machine
// ============================
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; /* 1 for tx, 0 for rx */
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) // arp
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) // ip
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) // TCP
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; /* 1 for tx, 0 for rx */
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
 
 
/tb.v
48,6 → 48,7
 
`include "debug_functions.v"
`include "system_functions.v"
`include "memory_configuration.v"
 
reg sysrst;
`ifdef XILINX_VIRTEX6_FPGA
99,7 → 100,8
wire mcb3_zio;
`endif
 
tri1 md_pad_io;
tri1 md; // bi-directional phy config data
wire mdc; // phy config clock
 
wire uart0_cts;
wire uart0_rx;
106,7 → 108,14
wire uart0_rts;
wire uart0_tx;
 
wire [3:0] eth_mtxd;
wire eth_mtxdv;
wire eth_mtxerr;
wire [3:0] eth_mrxd;
wire eth_mrxdv;
 
 
 
// ======================================
// Instantiate FPGA
// ======================================
152,24 → 161,43
 
// Ethernet MII signals
.mtx_clk_pad_i ( clk_25mhz ),
.mtxd_pad_o ( ),
.mtxen_pad_o ( ),
.mtxd_pad_o ( eth_mrxd ),
.mtxen_pad_o ( eth_mrxdv ),
.mtxerr_pad_o ( ),
.mrx_clk_pad_i ( clk_25mhz ),
.mrxd_pad_i ( 4'd0 ),
.mrxdv_pad_i ( 1'd0 ),
.mrxerr_pad_i ( 1'd0 ),
.mrxd_pad_i ( eth_mtxd ),
.mrxdv_pad_i ( eth_mtxdv ),
.mrxerr_pad_i ( eth_mtxerr ),
.mcoll_pad_i ( 1'd0 ),
.mcrs_pad_i ( 1'd0 ), // Assert Carrier Sense from PHY
.phy_reset_n ( ),
// Ethernet MD signals
.md_pad_io ( md_pad_io ),
.mdc_pad_o ( )
// Ethernet Management Data signals
.md_pad_io ( md ),
.mdc_pad_o ( mdc ),
// LEDs
.led ( )
);
 
 
 
// ======================================
// Instantiate Ethernet Test Device
// ======================================
eth_test u_eth_test(
.md_io ( md ),
.mdc_i ( mdc ),
.mtx_clk_i ( clk_25mhz ),
.mtxd_o ( eth_mtxd ),
.mtxdv_o ( eth_mtxdv ),
.mtxerr_o ( eth_mtxerr ),
.mrxd_i ( eth_mrxd ),
.mrxdv_i ( eth_mrxdv )
);
 
 
 
// ======================================
// Instantiate DDR3 Memory Model
// ======================================
202,6 → 230,7
`endif
 
 
 
// ======================================
// Instantiate Testbench UART
// ======================================
214,6 → 243,7
);
 
 
 
// ======================================
// Global module for xilinx hardware simulations
// ======================================
311,13 → 341,13
boot_mem_file_data = hex_chars_to_32bits (aligned_line[110*8-1:102*8]);
`ifdef AMBER_A25_CORE
boot_mem_file_data_128 = `U_BOOT_MEM.u_mem.mem[boot_mem_file_address[12:4]];
`U_BOOT_MEM.u_mem.mem[boot_mem_file_address[12:4]] =
boot_mem_file_data_128 = `U_BOOT_MEM.u_mem.mem[boot_mem_file_address[BOOT_MSB:4]];
`U_BOOT_MEM.u_mem.mem[boot_mem_file_address[BOOT_MSB:4]] =
insert_32_into_128 ( boot_mem_file_address[3:2],
boot_mem_file_data_128,
boot_mem_file_data );
`else
`U_BOOT_MEM.u_mem.mem[boot_mem_file_address[12:2]] = boot_mem_file_data;
`U_BOOT_MEM.u_mem.mem[boot_mem_file_address[BOOT_MSB:2]] = boot_mem_file_data;
`endif
`ifdef AMBER_LOAD_MEM_DEBUG

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.