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