//
|
//
|
// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org)
|
// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org)
|
//
|
//
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
// copy of this software and associated documentation files (the "Software"),
|
// copy of this software and associated documentation files (the "Software"),
|
// to deal in the Software without restriction, including without limitation
|
// to deal in the Software without restriction, including without limitation
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
// and/or sell copies of the Software, and to permit persons to whom the
|
// and/or sell copies of the Software, and to permit persons to whom the
|
// Software is furnished to do so, subject to the following conditions:
|
// Software is furnished to do so, subject to the following conditions:
|
//
|
//
|
// The above copyright notice and this permission notice shall be included
|
// The above copyright notice and this permission notice shall be included
|
// in all copies or substantial portions of the Software.
|
// in all copies or substantial portions of the Software.
|
//
|
//
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
// Simple network interface
|
// Simple network interface
|
//
|
//
|
// Implements a GMII-like byte-wide interface on one side, and
|
// Implements a GMII-like byte-wide interface on one side, and
|
// an IO-mapped interface to the tv80.
|
// an IO-mapped interface to the tv80.
|
|
|
// IO-interface:
|
// IO-interface:
|
// R0 -- Status register
|
// R0 -- Status register
|
// R1 -- Control register
|
// R1 -- Control register
|
// R2 -- RX Length (low)
|
// R2 -- RX Length (low)
|
// R3 -- RX Length (high)
|
// R3 -- RX Length (high)
|
// R4 -- RX Data
|
// R4 -- RX Data
|
// R5 -- TX Data
|
// R5 -- TX Data
|
// R6 -- Configuration
|
// R6 -- Configuration
|
|
|
// Status bits:
|
// Status bits:
|
// [0] RX Packet Ready
|
// [0] RX Packet Ready
|
// [1] TX Transmit Complete
|
// [1] TX Transmit Complete
|
|
|
// Control bits:
|
// Control bits:
|
// [0] Send TX Packet
|
// [0] Send TX Packet
|
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
|
|
module simple_gmii_core
|
module simple_gmii_core
|
#(parameter txbuf_sz = 512,
|
#(parameter txbuf_sz = 512,
|
parameter rxbuf_sz = 512,
|
parameter rxbuf_sz = 512,
|
parameter wr_ptr_sz = 10)
|
parameter wr_ptr_sz = 10)
|
(
|
(
|
input clk,
|
input clk,
|
input reset,
|
input reset,
|
|
|
// GMII Interface
|
// GMII Interface
|
input [7:0] rx_data,
|
input [7:0] rx_data,
|
input rx_clk,
|
input rx_clk,
|
input rx_dv,
|
input rx_dv,
|
input rx_er,
|
input rx_er,
|
|
|
output reg [7:0] tx_data,
|
output reg [7:0] tx_data,
|
input tx_clk,
|
input tx_clk,
|
output reg tx_dv,
|
output reg tx_dv,
|
output reg tx_er,
|
output reg tx_er,
|
|
|
// RX Buf RAM
|
// RX Buf RAM
|
output reg rxbuf_we,
|
output reg rxbuf_we,
|
output reg [wr_ptr_sz-1:0] rx_wr_ptr,
|
output reg [wr_ptr_sz-1:0] rx_wr_ptr,
|
output reg [wr_ptr_sz-1:0] rx_rd_ptr,
|
output reg [wr_ptr_sz-1:0] rx_rd_ptr,
|
input [7:0] rxbuf_data,
|
input [7:0] rxbuf_data,
|
|
|
// TX Buf RAM
|
// TX Buf RAM
|
output reg wr_sel_tx_data,
|
output reg wr_sel_tx_data,
|
output reg [wr_ptr_sz-1:0] txi_wr_ptr,
|
output reg [wr_ptr_sz-1:0] txi_wr_ptr,
|
//input [7:0] io_data_in,
|
//input [7:0] io_data_in,
|
output reg [wr_ptr_sz-1:0] txo_xm_ptr,
|
output reg [wr_ptr_sz-1:0] txo_xm_ptr,
|
input [7:0] txbuf_data,
|
input [7:0] txbuf_data,
|
|
|
// Register interface
|
// Register interface
|
output [1:0] status_set,
|
output [1:0] status_set,
|
input start_transmit, // control[0]
|
input start_transmit, // control[0]
|
output [15:0] rx_len,
|
output [15:0] rx_len,
|
output [7:0] rx_rd_data,
|
output [7:0] rx_rd_data,
|
input rx_rd_stb,
|
input rx_rd_stb,
|
//input [7:0] tx_wr_data,
|
//input [7:0] tx_wr_data,
|
input tx_wr_stb,
|
input tx_wr_stb,
|
input en_preamble // config[0]
|
input en_preamble // config[0]
|
);
|
);
|
|
|
//parameter io_base_addr = 8'hA0;
|
//parameter io_base_addr = 8'hA0;
|
//parameter txbuf_sz = 512, rxbuf_sz = 512;
|
//parameter txbuf_sz = 512, rxbuf_sz = 512;
|
//parameter wr_ptr_sz = 10;
|
//parameter wr_ptr_sz = 10;
|
|
|
//parameter st_tx_idle = 0, st_tx_xmit = 1;
|
//parameter st_tx_idle = 0, st_tx_xmit = 1;
|
parameter st_txi_idle = 1'b0, st_txi_xmit = 1'b1;
|
parameter st_txi_idle = 1'b0, st_txi_xmit = 1'b1;
|
parameter st_txo_idle = 2'b0, st_txo_pre = 2'b10, st_txo_xmit = 2'b11, st_txo_wait = 2'b01;
|
parameter st_txo_idle = 2'b0, st_txo_pre = 2'b10, st_txo_xmit = 2'b11, st_txo_wait = 2'b01;
|
parameter st_rxo_idle = 2'b00,
|
parameter st_rxo_idle = 2'b00,
|
st_rxo_ready = 2'b01,
|
st_rxo_ready = 2'b01,
|
st_rxo_ack = 2'b11;
|
st_rxo_ack = 2'b11;
|
|
|
parameter st_rxin_idle = 2'b00,
|
parameter st_rxin_idle = 2'b00,
|
st_rxin_pre = 2'b01,
|
st_rxin_pre = 2'b01,
|
st_rxin_receive = 2'b11,
|
st_rxin_receive = 2'b11,
|
st_rxin_hold = 2'b10;
|
st_rxin_hold = 2'b10;
|
|
|
parameter SFD = 8'hD5;
|
parameter SFD = 8'hD5;
|
|
|
//reg [wr_ptr_sz-1:0] tx_wr_ptr, tx_xm_ptr;
|
//reg [wr_ptr_sz-1:0] tx_wr_ptr, tx_xm_ptr;
|
reg [wr_ptr_sz-1:0] rx_count;
|
reg [wr_ptr_sz-1:0] rx_count;
|
reg txi_state;
|
reg txi_state;
|
reg [1:0] txo_state;
|
reg [1:0] txo_state;
|
reg txi_start;
|
reg txi_start;
|
wire txo_start;
|
wire txo_start;
|
reg txo_done;
|
reg txo_done;
|
wire txi_done;
|
wire txi_done;
|
reg [wr_ptr_sz-1:0] txo_wr_ptr;
|
reg [wr_ptr_sz-1:0] txo_wr_ptr;
|
|
|
|
|
reg stat_tx_complete;
|
reg stat_tx_complete;
|
|
|
reg stat_rx_avail;
|
reg stat_rx_avail;
|
|
|
reg [1:0] rxin_state;
|
reg [1:0] rxin_state;
|
reg rxin_complete;
|
reg rxin_complete;
|
reg [1:0] nxt_rxin_state;
|
reg [1:0] nxt_rxin_state;
|
reg nxt_rxin_complete;
|
reg nxt_rxin_complete;
|
reg [wr_ptr_sz-1:0] nxt_rx_wr_ptr;
|
reg [wr_ptr_sz-1:0] nxt_rx_wr_ptr;
|
reg rd_sel_rx_data;
|
reg rd_sel_rx_data;
|
reg [1:0] rxo_state;
|
reg [1:0] rxo_state;
|
wire rxo_complete;
|
wire rxo_complete;
|
reg rxo_ack;
|
reg rxo_ack;
|
wire rxin_ack;
|
wire rxin_ack;
|
|
|
//assign io_select = ((io_base_addr >> 3) == addr[7:3]);
|
//assign io_select = ((io_base_addr >> 3) == addr[7:3]);
|
|
|
//------------------------------
|
//------------------------------
|
// IO Read Mux
|
// IO Read Mux
|
//------------------------------
|
//------------------------------
|
|
|
assign rx_len = { {16-wr_ptr_sz{1'b0}}, rx_count };
|
assign rx_len = { {16-wr_ptr_sz{1'b0}}, rx_count };
|
assign status_set = { stat_tx_complete, stat_rx_avail };
|
assign status_set = { stat_tx_complete, stat_rx_avail };
|
assign rx_rd_data = rxbuf_data;
|
assign rx_rd_data = rxbuf_data;
|
|
|
//------------------------------
|
//------------------------------
|
// Receive Logic
|
// Receive Logic
|
//------------------------------
|
//------------------------------
|
|
|
always @*
|
always @*
|
begin
|
begin
|
rd_sel_rx_data = rx_rd_stb;
|
rd_sel_rx_data = rx_rd_stb;
|
//rxbuf_we = ((rxin_state == st_rxin_idle) | (rxin_state == st_rxin_receive)) & rx_dv;
|
//rxbuf_we = ((rxin_state == st_rxin_idle) | (rxin_state == st_rxin_receive)) & rx_dv;
|
end
|
end
|
/*
|
/*
|
ram_1r_1w #(8, rxbuf_sz, wr_ptr_sz) rxbuf
|
ram_1r_1w #(8, rxbuf_sz, wr_ptr_sz) rxbuf
|
(.clk (rx_clk),
|
(.clk (rx_clk),
|
.wr_en (rxbuf_we),
|
.wr_en (rxbuf_we),
|
.wr_addr (rx_wr_ptr),
|
.wr_addr (rx_wr_ptr),
|
.wr_data (rx_data),
|
.wr_data (rx_data),
|
|
|
.rd_addr (rx_rd_ptr),
|
.rd_addr (rx_rd_ptr),
|
.rd_data (rxbuf_data));
|
.rd_data (rxbuf_data));
|
*/
|
*/
|
|
|
always @*
|
always @*
|
begin
|
begin
|
rxbuf_we = 0;
|
rxbuf_we = 0;
|
nxt_rxin_complete = rxin_complete;
|
nxt_rxin_complete = rxin_complete;
|
nxt_rxin_state = rxin_state;
|
nxt_rxin_state = rxin_state;
|
nxt_rx_wr_ptr = rx_wr_ptr;
|
nxt_rx_wr_ptr = rx_wr_ptr;
|
|
|
case (rxin_state)
|
case (rxin_state)
|
st_rxin_idle :
|
st_rxin_idle :
|
begin
|
begin
|
if (rx_dv)
|
if (rx_dv)
|
begin
|
begin
|
nxt_rxin_complete = 0;
|
nxt_rxin_complete = 0;
|
if (en_preamble & (rx_data != SFD))
|
if (en_preamble & (rx_data != SFD))
|
nxt_rxin_state = st_rxin_pre;
|
nxt_rxin_state = st_rxin_pre;
|
else
|
else
|
begin
|
begin
|
nxt_rx_wr_ptr = rx_wr_ptr + 1;
|
nxt_rx_wr_ptr = rx_wr_ptr + 1;
|
nxt_rxin_state = st_rxin_receive;
|
nxt_rxin_state = st_rxin_receive;
|
rxbuf_we = 1;
|
rxbuf_we = 1;
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
nxt_rx_wr_ptr = 0;
|
nxt_rx_wr_ptr = 0;
|
end
|
end
|
end // case: st_rxin_idle
|
end // case: st_rxin_idle
|
|
|
st_rxin_pre :
|
st_rxin_pre :
|
begin
|
begin
|
if (rx_data == SFD)
|
if (rx_data == SFD)
|
nxt_rxin_state = st_rxin_receive;
|
nxt_rxin_state = st_rxin_receive;
|
end
|
end
|
|
|
st_rxin_receive :
|
st_rxin_receive :
|
begin
|
begin
|
if (rx_dv)
|
if (rx_dv)
|
begin
|
begin
|
nxt_rx_wr_ptr = rx_wr_ptr + 1;
|
nxt_rx_wr_ptr = rx_wr_ptr + 1;
|
rxbuf_we = 1;
|
rxbuf_we = 1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
nxt_rxin_state = st_rxin_hold;
|
nxt_rxin_state = st_rxin_hold;
|
nxt_rxin_complete = 1;
|
nxt_rxin_complete = 1;
|
end
|
end
|
end
|
end
|
|
|
st_rxin_hold :
|
st_rxin_hold :
|
begin
|
begin
|
if (rxin_ack & !rx_dv)
|
if (rxin_ack & !rx_dv)
|
begin
|
begin
|
nxt_rxin_state = st_rxin_idle;
|
nxt_rxin_state = st_rxin_idle;
|
nxt_rxin_complete = 0;
|
nxt_rxin_complete = 0;
|
end
|
end
|
end
|
end
|
|
|
default :
|
default :
|
nxt_rxin_state = st_rxin_idle;
|
nxt_rxin_state = st_rxin_idle;
|
endcase // case(rxin_state)
|
endcase // case(rxin_state)
|
end // always @ *
|
end // always @ *
|
|
|
always @(posedge rx_clk)
|
always @(posedge rx_clk)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
begin
|
begin
|
rxin_state <= #1 st_rxin_idle;
|
rxin_state <= #1 st_rxin_idle;
|
rxin_complete <= #1 0;
|
rxin_complete <= #1 0;
|
rx_wr_ptr <= #1 0;
|
rx_wr_ptr <= #1 0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
rxin_state <= #1 nxt_rxin_state;
|
rxin_state <= #1 nxt_rxin_state;
|
rxin_complete <= #1 nxt_rxin_complete;
|
rxin_complete <= #1 nxt_rxin_complete;
|
rx_wr_ptr <= #1 nxt_rx_wr_ptr;
|
rx_wr_ptr <= #1 nxt_rx_wr_ptr;
|
end // else: !if(reset)
|
end // else: !if(reset)
|
end // always @ (posedge rx_clk)
|
end // always @ (posedge rx_clk)
|
|
|
/*
|
/*
|
always @(posedge rx_clk)
|
always @(posedge rx_clk)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
begin
|
begin
|
rxin_state <= #1 st_rxin_idle;
|
rxin_state <= #1 st_rxin_idle;
|
rxin_complete <= #1 0;
|
rxin_complete <= #1 0;
|
rx_wr_ptr <= #1 0;
|
rx_wr_ptr <= #1 0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
case (rxin_state)
|
case (rxin_state)
|
st_rxin_idle :
|
st_rxin_idle :
|
begin
|
begin
|
if (rx_dv)
|
if (rx_dv)
|
begin
|
begin
|
rxin_complete <= #1 0;
|
rxin_complete <= #1 0;
|
if (en_preamble & (rx_data != SFD))
|
if (en_preamble & (rx_data != SFD))
|
rxin_state <= #1 st_rxin_pre;
|
rxin_state <= #1 st_rxin_pre;
|
else
|
else
|
begin
|
begin
|
rx_wr_ptr <= #1 rx_wr_ptr + 1;
|
rx_wr_ptr <= #1 rx_wr_ptr + 1;
|
rxin_state <= #1 st_rxin_receive;
|
rxin_state <= #1 st_rxin_receive;
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
rx_wr_ptr <= #1 0;
|
rx_wr_ptr <= #1 0;
|
end
|
end
|
end // case: st_rxin_idle
|
end // case: st_rxin_idle
|
|
|
st_rxin_pre :
|
st_rxin_pre :
|
begin
|
begin
|
if (rx_data == SFD)
|
if (rx_data == SFD)
|
rxin_state <= #1 st_rxin_receive;
|
rxin_state <= #1 st_rxin_receive;
|
end
|
end
|
|
|
st_rxin_receive :
|
st_rxin_receive :
|
begin
|
begin
|
if (rx_dv)
|
if (rx_dv)
|
rx_wr_ptr <= #1 rx_wr_ptr + 1;
|
rx_wr_ptr <= #1 rx_wr_ptr + 1;
|
else
|
else
|
begin
|
begin
|
rxin_state <= #1 st_rxin_hold;
|
rxin_state <= #1 st_rxin_hold;
|
rxin_complete <= #1 1;
|
rxin_complete <= #1 1;
|
end
|
end
|
end
|
end
|
|
|
st_rxin_hold :
|
st_rxin_hold :
|
begin
|
begin
|
if (rxin_ack & !rx_dv)
|
if (rxin_ack & !rx_dv)
|
begin
|
begin
|
rxin_state <= #1 st_rxin_idle;
|
rxin_state <= #1 st_rxin_idle;
|
rxin_complete <= #1 0;
|
rxin_complete <= #1 0;
|
end
|
end
|
end
|
end
|
|
|
default :
|
default :
|
rxin_state <= #1 st_rxin_idle;
|
rxin_state <= #1 st_rxin_idle;
|
endcase // case(rxin_state)
|
endcase // case(rxin_state)
|
end // else: !if(reset)
|
end // else: !if(reset)
|
end // always @ (posedge rx_clk)
|
end // always @ (posedge rx_clk)
|
*/
|
*/
|
|
|
sync2 comp_sync (clk, rxin_complete, rxo_complete);
|
sync2 comp_sync (clk, rxin_complete, rxo_complete);
|
sync2 ack_sync (rx_clk, rxo_ack, rxin_ack);
|
sync2 ack_sync (rx_clk, rxo_ack, rxin_ack);
|
|
|
always @(posedge clk)
|
always @(posedge clk)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
begin
|
begin
|
rx_count <= #1 0;
|
rx_count <= #1 0;
|
rxo_state <= #1 st_rxo_idle;
|
rxo_state <= #1 st_rxo_idle;
|
stat_rx_avail <= #1 0;
|
stat_rx_avail <= #1 0;
|
rxo_ack <= #1 0;
|
rxo_ack <= #1 0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
case (rxo_state)
|
case (rxo_state)
|
st_rxo_idle :
|
st_rxo_idle :
|
begin
|
begin
|
rx_rd_ptr <= #1 0;
|
rx_rd_ptr <= #1 0;
|
if (rxin_complete)
|
if (rxin_complete)
|
begin
|
begin
|
rxo_state <= #1 st_rxo_ready;
|
rxo_state <= #1 st_rxo_ready;
|
stat_rx_avail <= #1 1;
|
stat_rx_avail <= #1 1;
|
rx_count <= #1 rx_wr_ptr;
|
rx_count <= #1 rx_wr_ptr;
|
end
|
end
|
end
|
end
|
|
|
st_rxo_ready :
|
st_rxo_ready :
|
begin
|
begin
|
if (rd_sel_rx_data)
|
if (rd_sel_rx_data)
|
rx_rd_ptr <= #1 rx_rd_ptr + 1;
|
rx_rd_ptr <= #1 rx_rd_ptr + 1;
|
|
|
if (rx_rd_ptr == rx_count)
|
if (rx_rd_ptr == rx_count)
|
begin
|
begin
|
rxo_ack <= #1 1;
|
rxo_ack <= #1 1;
|
rxo_state <= #1 st_rxo_ack;
|
rxo_state <= #1 st_rxo_ack;
|
stat_rx_avail <= #1 0;
|
stat_rx_avail <= #1 0;
|
end
|
end
|
end // case: st_rxo_ready
|
end // case: st_rxo_ready
|
|
|
st_rxo_ack :
|
st_rxo_ack :
|
begin
|
begin
|
if (!rxo_complete)
|
if (!rxo_complete)
|
rxo_state <= #1 st_rxo_idle;
|
rxo_state <= #1 st_rxo_idle;
|
end
|
end
|
|
|
default :
|
default :
|
rxo_state <= #1 st_rxo_idle;
|
rxo_state <= #1 st_rxo_idle;
|
endcase // case(rxo_state)
|
endcase // case(rxo_state)
|
end // else: !if(reset)
|
end // else: !if(reset)
|
end // always @ (posedge clk)
|
end // always @ (posedge clk)
|
|
|
//------------------------------
|
//------------------------------
|
// Transmit Logic
|
// Transmit Logic
|
//------------------------------
|
//------------------------------
|
|
|
always @*
|
always @*
|
begin
|
begin
|
wr_sel_tx_data = tx_wr_stb;
|
wr_sel_tx_data = tx_wr_stb;
|
end
|
end
|
|
|
/*
|
/*
|
ram_1r_1w #(8, txbuf_sz, wr_ptr_sz) txbuf
|
ram_1r_1w #(8, txbuf_sz, wr_ptr_sz) txbuf
|
(.clk (clk),
|
(.clk (clk),
|
.wr_en (wr_sel_tx_data),
|
.wr_en (wr_sel_tx_data),
|
.wr_addr (txi_wr_ptr),
|
.wr_addr (txi_wr_ptr),
|
.wr_data (io_data_in),
|
.wr_data (io_data_in),
|
|
|
.rd_addr (txo_xm_ptr),
|
.rd_addr (txo_xm_ptr),
|
.rd_data (txbuf_data));
|
.rd_data (txbuf_data));
|
*/
|
*/
|
|
|
always @(posedge clk)
|
always @(posedge clk)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
begin
|
begin
|
txi_state <= #1 st_txi_idle;
|
txi_state <= #1 st_txi_idle;
|
txi_start <= #1 0;
|
txi_start <= #1 0;
|
txi_wr_ptr <= #1 0;
|
txi_wr_ptr <= #1 0;
|
stat_tx_complete <= #1 0;
|
stat_tx_complete <= #1 0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
case (txi_state)
|
case (txi_state)
|
st_txi_idle :
|
st_txi_idle :
|
begin
|
begin
|
stat_tx_complete <= #1 0;
|
stat_tx_complete <= #1 0;
|
if (start_transmit)
|
if (start_transmit)
|
begin
|
begin
|
txi_state <= #1 st_txi_xmit;
|
txi_state <= #1 st_txi_xmit;
|
txi_start <= #1 1;
|
txi_start <= #1 1;
|
|
|
end
|
end
|
else if (wr_sel_tx_data)
|
else if (wr_sel_tx_data)
|
begin
|
begin
|
txi_wr_ptr <= #1 txi_wr_ptr + 1;
|
txi_wr_ptr <= #1 txi_wr_ptr + 1;
|
end
|
end
|
end
|
end
|
|
|
st_txi_xmit :
|
st_txi_xmit :
|
begin
|
begin
|
if (txi_done)
|
if (txi_done)
|
begin
|
begin
|
txi_start <= #1 0;
|
txi_start <= #1 0;
|
txi_state <= #1 st_txi_idle;
|
txi_state <= #1 st_txi_idle;
|
txi_wr_ptr <= #1 0;
|
txi_wr_ptr <= #1 0;
|
stat_tx_complete <= #1 1;
|
stat_tx_complete <= #1 1;
|
end
|
end
|
end
|
end
|
|
|
default :
|
default :
|
txi_state <= #1 st_txi_idle;
|
txi_state <= #1 st_txi_idle;
|
endcase // case(txi_state)
|
endcase // case(txi_state)
|
end
|
end
|
end // always @ (posedge clk)
|
end // always @ (posedge clk)
|
|
|
sync2 tx_start_sync (tx_clk, txi_start, txo_start);
|
sync2 tx_start_sync (tx_clk, txi_start, txo_start);
|
sync2 tx_done_sync (clk, txo_done, txi_done);
|
sync2 tx_done_sync (clk, txo_done, txi_done);
|
|
|
|
|
always @(posedge tx_clk)
|
always @(posedge tx_clk)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
begin
|
begin
|
txo_state <= #1 st_txo_idle;
|
txo_state <= #1 st_txo_idle;
|
txo_wr_ptr <= #1 0;
|
txo_wr_ptr <= #1 0;
|
txo_xm_ptr <= #1 0;
|
txo_xm_ptr <= #1 0;
|
tx_data <= #1 0;
|
tx_data <= #1 0;
|
tx_dv <= #1 0;
|
tx_dv <= #1 0;
|
tx_er <= #1 0;
|
tx_er <= #1 0;
|
txo_done <= #1 0;
|
txo_done <= #1 0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
case (txo_state)
|
case (txo_state)
|
st_txo_idle :
|
st_txo_idle :
|
begin
|
begin
|
txo_xm_ptr <= #1 0;
|
txo_xm_ptr <= #1 0;
|
tx_dv <= #1 0;
|
tx_dv <= #1 0;
|
tx_er <= #1 0;
|
tx_er <= #1 0;
|
|
|
if (txo_start)
|
if (txo_start)
|
begin
|
begin
|
if (en_preamble)
|
if (en_preamble)
|
txo_state <= #1 st_txo_pre;
|
txo_state <= #1 st_txo_pre;
|
else
|
else
|
txo_state <= #1 st_txo_xmit;
|
txo_state <= #1 st_txo_xmit;
|
txo_wr_ptr <= #1 txi_wr_ptr;
|
txo_wr_ptr <= #1 txi_wr_ptr;
|
end
|
end
|
end
|
end
|
|
|
st_txo_pre :
|
st_txo_pre :
|
begin
|
begin
|
tx_er <= #1 0;
|
tx_er <= #1 0;
|
tx_dv <= #1 1;
|
tx_dv <= #1 1;
|
if (txo_xm_ptr == 7)
|
if (txo_xm_ptr == 7)
|
begin
|
begin
|
txo_xm_ptr <= #1 0;
|
txo_xm_ptr <= #1 0;
|
txo_state <= #1 st_txo_xmit;
|
txo_state <= #1 st_txo_xmit;
|
tx_data <= #1 8'hd5;
|
tx_data <= #1 8'hd5;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
txo_xm_ptr <= #1 txo_xm_ptr + 1;
|
txo_xm_ptr <= #1 txo_xm_ptr + 1;
|
tx_data <= #1 8'h55;
|
tx_data <= #1 8'h55;
|
end
|
end
|
end
|
end
|
|
|
st_txo_xmit :
|
st_txo_xmit :
|
begin
|
begin
|
if (txo_xm_ptr == txo_wr_ptr)
|
if (txo_xm_ptr == txo_wr_ptr)
|
begin
|
begin
|
tx_dv <= #1 0;
|
tx_dv <= #1 0;
|
tx_er <= #1 0;
|
tx_er <= #1 0;
|
txo_state <= #1 st_txo_wait;
|
txo_state <= #1 st_txo_wait;
|
txo_wr_ptr <= #1 0;
|
txo_wr_ptr <= #1 0;
|
txo_done <= #1 1;
|
txo_done <= #1 1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
tx_data <= #1 txbuf_data;
|
tx_data <= #1 txbuf_data;
|
tx_dv <= #1 1;
|
tx_dv <= #1 1;
|
tx_er <= #1 0;
|
tx_er <= #1 0;
|
txo_xm_ptr <= #1 txo_xm_ptr + 1;
|
txo_xm_ptr <= #1 txo_xm_ptr + 1;
|
end
|
end
|
end // case: st_txo_xmit
|
end // case: st_txo_xmit
|
|
|
st_txo_wait :
|
st_txo_wait :
|
begin
|
begin
|
if (!txo_start)
|
if (!txo_start)
|
begin
|
begin
|
txo_done <= #1 0;
|
txo_done <= #1 0;
|
txo_state <= #1 st_txo_idle;
|
txo_state <= #1 st_txo_idle;
|
end
|
end
|
end
|
end
|
|
|
default :
|
default :
|
begin
|
begin
|
txo_state <= #1 st_txo_idle;
|
txo_state <= #1 st_txo_idle;
|
end
|
end
|
endcase // case(tx_state)
|
endcase // case(tx_state)
|
end // else: !if(reset)
|
end // else: !if(reset)
|
end // always @ (posedge clk)
|
end // always @ (posedge clk)
|
|
|
endmodule
|
endmodule
|
|
|
|
|