Line 84... |
Line 84... |
app_tx_fifo_empty,
|
app_tx_fifo_empty,
|
|
|
//dfl and back
|
//dfl and back
|
df2tx_dfl_dn,
|
df2tx_dfl_dn,
|
|
|
//application
|
|
app_send_pause,
|
|
|
|
//FCS
|
//FCS
|
tc2tx_fcs,
|
tc2tx_fcs,
|
|
|
//Configuration
|
//Configuration
|
cf2tx_tstate_mode,
|
|
cf2tx_ch_en,
|
cf2tx_ch_en,
|
cf2tx_pad_enable,
|
cf2tx_pad_enable,
|
cf2tx_append_fcs,
|
cf2tx_append_fcs,
|
cf_mac_mode,
|
cf_mac_mode,
|
cf_mac_sa,
|
cf_mac_sa,
|
cf2tx_pause_quanta,
|
|
cf2tx_force_bad_fcs,
|
cf2tx_force_bad_fcs,
|
|
|
//RX pause
|
|
rx2tx_pause,
|
|
send_pause_active_out,
|
|
app_clk,
|
app_clk,
|
set_fifo_undrn,
|
set_fifo_undrn,
|
|
|
//MII interface
|
//MII interface
|
mi2tx_byte_ack,
|
mi2tx_byte_ack,
|
Line 122... |
Line 114... |
parameter CORE_PAYLOAD_SIZE = 16'h3C ; //60 bytes =>
|
parameter CORE_PAYLOAD_SIZE = 16'h3C ; //60 bytes =>
|
// (12(add)+2(len)+46(pay))*2
|
// (12(add)+2(len)+46(pay))*2
|
|
|
|
|
input cf2tx_ch_en; //transmit enable application clock
|
input cf2tx_ch_en; //transmit enable application clock
|
input cf2tx_tstate_mode; //used for OFN's tstate enable on authentication interface
|
|
input app_tx_rdy; //tx fifo management, enough buffer to tx
|
input app_tx_rdy; //tx fifo management, enough buffer to tx
|
input tx_end_frame; //Current DWORD marks end of frame
|
input tx_end_frame; //Current DWORD marks end of frame
|
input [7:0] app_tx_dt_in; //double word data from the TX fifo mgmt
|
input [7:0] app_tx_dt_in; //double word data from the TX fifo mgmt
|
input app_tx_fifo_empty; //TX fifo is empty, if there were a data
|
input app_tx_fifo_empty; //TX fifo is empty, if there were a data
|
//data request when app_tx_fifo_empty is asserted
|
//data request when app_tx_fifo_empty is asserted
|
//would result in FIFO underrun and error cond
|
//would result in FIFO underrun and error cond
|
input app_send_pause;
|
|
input [31:0] tc2tx_fcs;
|
input [31:0] tc2tx_fcs;
|
|
|
//defferral inputs
|
//defferral inputs
|
input df2tx_dfl_dn; //IPG time between frames is satisfied
|
input df2tx_dfl_dn; //IPG time between frames is satisfied
|
|
|
Line 143... |
Line 133... |
//cf2tx_pad_enable and the current frame is small
|
//cf2tx_pad_enable and the current frame is small
|
//FCS is computed and appended to the frame
|
//FCS is computed and appended to the frame
|
//irrespective of this signal
|
//irrespective of this signal
|
input cf_mac_mode; // 1 is GMII 0 10/100
|
input cf_mac_mode; // 1 is GMII 0 10/100
|
input [47:0] cf_mac_sa;
|
input [47:0] cf_mac_sa;
|
input [15:0] cf2tx_pause_quanta;
|
|
input cf2tx_force_bad_fcs;
|
input cf2tx_force_bad_fcs;
|
//RX pause frame received
|
|
input rx2tx_pause; //in full duplex mode, the RX has received
|
|
//a pause frame, hence the TX is requested to
|
|
//hold transfers after the transmission of the
|
|
//current transfer. level signal
|
|
//from MII or RMII
|
|
input mi2tx_byte_ack; //MII interface accepted last byte
|
input mi2tx_byte_ack; //MII interface accepted last byte
|
input tx_clk;
|
input tx_clk;
|
input tx_reset_n;
|
input tx_reset_n;
|
input app_reset_n;
|
input app_reset_n;
|
|
|
Line 178... |
Line 161... |
output tx_ch_en; // MANDAR
|
output tx_ch_en; // MANDAR
|
|
|
input phy_tx_en; // mfilardo ofn auth fix.
|
input phy_tx_en; // mfilardo ofn auth fix.
|
|
|
input app_clk;
|
input app_clk;
|
output send_pause_active_out;
|
|
output set_fifo_undrn; // Description: At GMII Interface ,
|
output set_fifo_undrn; // Description: At GMII Interface ,
|
// abug after a transmit fifo underun was found.
|
// abug after a transmit fifo underun was found.
|
// The packet after a packet that
|
// The packet after a packet that
|
// underran has 1 too few bytes .
|
// underran has 1 too few bytes .
|
|
|
Line 195... |
Line 177... |
|
|
parameter dt_idle_st = 12'b000000000000;
|
parameter dt_idle_st = 12'b000000000000;
|
parameter dt_xfr_st = 12'b000000000001;
|
parameter dt_xfr_st = 12'b000000000001;
|
parameter dt_pad_st = 12'b000000000010;
|
parameter dt_pad_st = 12'b000000000010;
|
parameter dt_fcs_st = 12'b000000000100;
|
parameter dt_fcs_st = 12'b000000000100;
|
parameter dt_pause_xfr_st = 12'b000010000000;
|
|
parameter dt_pause_pad_st = 12'b000100000000;
|
|
parameter dt_pause_fcs_st = 12'b001000000000;
|
|
|
|
|
|
wire tx_commit_read;
|
wire tx_commit_read;
|
wire tx_dt_rd; //request TX FIFO for more data
|
wire tx_dt_rd; //request TX FIFO for more data
|
wire tx2tc_fcs_active; //FCS is currently transmitted
|
wire tx2tc_fcs_active; //FCS is currently transmitted
|
Line 247... |
Line 226... |
reg set_fifo_undrn, clr_fifo_undrn, fifo_undrn;
|
reg set_fifo_undrn, clr_fifo_undrn, fifo_undrn;
|
reg commit_read_sent;
|
reg commit_read_sent;
|
reg clr_first_dfl, set_first_dfl;
|
reg clr_first_dfl, set_first_dfl;
|
|
|
wire tx_lst_xfr;
|
wire tx_lst_xfr;
|
wire tx_pause_sync;
|
|
reg inc_pause_index, clr_pause_index;
|
|
reg send_pause_active;
|
|
wire send_pause_sync;
|
|
|
|
reg [4:0] pause_index;
|
|
|
|
reg tx_lst_xfr_fcs_reg;
|
reg tx_lst_xfr_fcs_reg;
|
wire [15:0] tx_byte_cntr_int;
|
wire [15:0] tx_byte_cntr_int;
|
|
|
reg cur_idle_st_del;
|
reg cur_idle_st_del;
|
|
|
reg app_tx_rdy_dly;
|
reg app_tx_rdy_dly;
|
|
|
reg send_pause_active_s1;
|
|
reg send_pause_active_out;
|
|
|
|
always @(posedge app_clk or negedge app_reset_n) begin
|
|
if (!app_reset_n) begin
|
|
send_pause_active_s1 <= 1'b0;
|
|
send_pause_active_out <= 1'b0;
|
|
end
|
|
else begin
|
|
send_pause_active_s1 <= send_pause_active;
|
|
send_pause_active_out <= send_pause_active_s1;
|
|
end
|
|
end
|
|
|
|
always @(posedge tx_clk or negedge tx_reset_n) begin
|
always @(posedge tx_clk or negedge tx_reset_n) begin
|
if (!tx_reset_n) begin
|
if (!tx_reset_n) begin
|
app_tx_rdy_dly <= 1'b0;
|
app_tx_rdy_dly <= 1'b0;
|
end
|
end
|
Line 298... |
Line 259... |
assign tx2mi_end_transmit = tx_lst_xfr;
|
assign tx2mi_end_transmit = tx_lst_xfr;
|
|
|
assign tx_lst_xfr = tx_lst_xfr_dt || tx_lst_xfr_fcs;
|
assign tx_lst_xfr = tx_lst_xfr_dt || tx_lst_xfr_fcs;
|
|
|
//To take care of 1 less byte count when fcs is not appended.
|
//To take care of 1 less byte count when fcs is not appended.
|
assign tx_byte_cntr_int = ((curr_dt_st == dt_fcs_st) ||
|
assign tx_byte_cntr_int = (curr_dt_st == dt_fcs_st) ? tx_byte_cntr : tx_byte_cntr + 16'h1;
|
(curr_dt_st == dt_pause_fcs_st)) ? tx_byte_cntr : tx_byte_cntr + 16'h1;
|
|
|
|
always @(posedge tx_clk or negedge tx_reset_n)
|
always @(posedge tx_clk or negedge tx_reset_n)
|
begin
|
begin
|
if (!tx_reset_n)
|
if (!tx_reset_n)
|
begin
|
begin
|
Line 323... |
Line 283... |
end // always @ (posedge tx_clk or negedge tx_reset_n)
|
end // always @ (posedge tx_clk or negedge tx_reset_n)
|
|
|
|
|
|
|
|
|
half_dup_dble_reg U_dble_reg1 (
|
|
//outputs
|
|
.sync_out_pulse(tx_pause_sync),
|
|
//inputs
|
|
.in_pulse(rx2tx_pause),
|
|
.dest_clk(tx_clk),
|
|
.reset_n(tx_reset_n)
|
|
);
|
|
|
|
half_dup_dble_reg U_dble_reg2 (
|
half_dup_dble_reg U_dble_reg2 (
|
//outputs
|
//outputs
|
.sync_out_pulse(tx_ch_en),
|
.sync_out_pulse(tx_ch_en),
|
//inputs
|
//inputs
|
.in_pulse(cf2tx_ch_en),
|
.in_pulse(cf2tx_ch_en),
|
.dest_clk(tx_clk),
|
.dest_clk(tx_clk),
|
.reset_n(tx_reset_n)
|
.reset_n(tx_reset_n)
|
);
|
);
|
|
|
|
|
half_dup_dble_reg U_dble_reg3 (
|
|
//outputs
|
|
.sync_out_pulse(send_pause_sync),
|
|
//inputs
|
|
.in_pulse(app_send_pause),
|
|
.dest_clk(tx_clk),
|
|
.reset_n(tx_reset_n)
|
|
);
|
|
|
|
half_dup_dble_reg U_dble_reg4 (
|
half_dup_dble_reg U_dble_reg4 (
|
//outputs
|
//outputs
|
.sync_out_pulse(cfg_force_bad_fcs_pulse),
|
.sync_out_pulse(cfg_force_bad_fcs_pulse),
|
//inputs
|
//inputs
|
Line 389... |
Line 332... |
//combinatorial process
|
//combinatorial process
|
//always @(curr_dt_st or mi2tx_byte_ack or app_tx_fifo_empty
|
//always @(curr_dt_st or mi2tx_byte_ack or app_tx_fifo_empty
|
always @(curr_dt_st or mi2tx_byte_ack or app_tx_fifo_empty
|
always @(curr_dt_st or mi2tx_byte_ack or app_tx_fifo_empty
|
or tx_end_frame_reg or commit_read_sent
|
or tx_end_frame_reg or commit_read_sent
|
or tx_byte_cntr or tx_fcs_dn_reg or cf2tx_pad_enable or tx_ch_en
|
or tx_byte_cntr or tx_fcs_dn_reg or cf2tx_pad_enable or tx_ch_en
|
or df2tx_dfl_dn or tx_pause_sync or app_tx_rdy
|
or df2tx_dfl_dn or app_tx_rdy
|
or strt_fcs_reg
|
or strt_fcs_reg
|
or tx_end_frame or tx_clk
|
or tx_end_frame or tx_clk
|
or cf2tx_append_fcs
|
or cf2tx_append_fcs
|
or app_tx_rdy_dly or send_pause_sync or pause_index or cur_idle_st_del)
|
or app_tx_rdy_dly or cur_idle_st_del)
|
begin
|
begin
|
nxt_dt_st = curr_dt_st;
|
nxt_dt_st = curr_dt_st;
|
tx_fsm_rd = 0;
|
tx_fsm_rd = 0;
|
tx_byte_valid = 0;
|
tx_byte_valid = 0;
|
set_bad_fcs = 0;
|
set_bad_fcs = 0;
|
Line 411... |
Line 354... |
clr_pad_byte = 0;
|
clr_pad_byte = 0;
|
set_fifo_undrn = 0;
|
set_fifo_undrn = 0;
|
clr_fifo_undrn = 0;
|
clr_fifo_undrn = 0;
|
clr_first_dfl = 0;
|
clr_first_dfl = 0;
|
set_first_dfl = 0;
|
set_first_dfl = 0;
|
send_pause_active = 0;
|
|
inc_pause_index = 0;
|
|
clr_pause_index = 0;
|
|
case (curr_dt_st)
|
case (curr_dt_st)
|
dt_idle_st :
|
dt_idle_st :
|
begin
|
begin
|
//clear early state
|
//clear early state
|
clr_pad_byte = 1;
|
clr_pad_byte = 1;
|
Line 426... |
Line 366... |
//wait until there is enough data in the TX FIFO
|
//wait until there is enough data in the TX FIFO
|
//and tx_enabled and not waiting for pause period
|
//and tx_enabled and not waiting for pause period
|
//in the case of full duplex
|
//in the case of full duplex
|
if (tx_ch_en) //config, channel enable
|
if (tx_ch_en) //config, channel enable
|
begin
|
begin
|
if (send_pause_sync && df2tx_dfl_dn)
|
if (app_tx_rdy && df2tx_dfl_dn)
|
begin
|
|
// this ifdef is a bug fix. A pending pause can cause ifg to be 1 cycle short.
|
|
nxt_dt_st = dt_pause_xfr_st;
|
|
strt_preamble = 1;
|
|
end
|
|
else if (app_tx_rdy && df2tx_dfl_dn && !tx_pause_sync)
|
|
begin
|
begin
|
tx_fsm_rd = 1;
|
tx_fsm_rd = 1;
|
nxt_dt_st = dt_xfr_st;
|
nxt_dt_st = dt_xfr_st;
|
strt_preamble = 1;
|
strt_preamble = 1;
|
end
|
end
|
Line 585... |
Line 519... |
begin
|
begin
|
nxt_dt_st = dt_fcs_st;
|
nxt_dt_st = dt_fcs_st;
|
end // else: !if(tx_fcs_dn)
|
end // else: !if(tx_fcs_dn)
|
end // case: dt_fcs_st
|
end // case: dt_fcs_st
|
|
|
dt_pause_xfr_st :
|
|
begin
|
|
tx_byte_valid = 1;
|
|
send_pause_active = 1;
|
|
// Send the Pause Frame out
|
|
if (mi2tx_byte_ack)
|
|
begin
|
|
if (pause_index == 5'd18)
|
|
begin
|
|
clr_pause_index = 1;
|
|
nxt_dt_st = dt_pause_pad_st;
|
|
end
|
|
else
|
|
begin
|
|
inc_pause_index = 1;
|
|
nxt_dt_st = dt_pause_xfr_st;
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
nxt_dt_st = dt_pause_xfr_st;
|
|
end
|
|
end // case: dt_pause_xfr_st
|
|
|
|
dt_pause_pad_st :
|
|
begin
|
|
// Append Padding to the Packet
|
|
tx_byte_valid = 1;
|
|
set_pad_byte = 1;
|
|
if (mi2tx_byte_ack && (tx_byte_cntr == CORE_PAYLOAD_SIZE - 1))
|
|
begin
|
|
strt_fcs = 1;
|
|
nxt_dt_st = dt_pause_fcs_st;
|
|
end // if (mi2tx_byte_ack &&
|
|
// (tx_byte_cntr == CORE_PAYLOAD_SIZE - 1))
|
|
else
|
|
nxt_dt_st = dt_pause_pad_st;
|
|
end // case: dt_pause_pad_st
|
|
|
|
dt_pause_fcs_st :
|
|
begin
|
|
// Wait for the FCS to be sent
|
|
if (tx_fcs_dn_reg)
|
|
begin
|
|
e_tx_sts_vld = 1;
|
|
nxt_dt_st = dt_idle_st;
|
|
end
|
|
else
|
|
begin
|
|
nxt_dt_st = dt_pause_fcs_st;
|
|
end
|
|
end // case: dt_pause_fcs_st
|
|
|
|
|
|
default :
|
default :
|
begin
|
begin
|
nxt_dt_st = dt_idle_st;
|
nxt_dt_st = dt_idle_st;
|
Line 836... |
Line 718... |
if (e_tx_sts_vld)
|
if (e_tx_sts_vld)
|
tx_end_frame_reg <= 0;
|
tx_end_frame_reg <= 0;
|
end // else: !if(!tx_reset_n)
|
end // else: !if(!tx_reset_n)
|
end // always @ (posedge tx_clk or negedge tx_reset_n)
|
end // always @ (posedge tx_clk or negedge tx_reset_n)
|
|
|
//Pause index counters
|
|
always @(posedge tx_clk or negedge tx_reset_n)
|
|
begin
|
|
if (!tx_reset_n)
|
|
pause_index <= 5'd0;
|
|
else
|
|
begin
|
|
if (clr_pause_index)
|
|
pause_index <= 5'd0;
|
|
else if (inc_pause_index)
|
|
pause_index <= pause_index + 1;
|
|
end // else: !if(!tx_reset_n)
|
|
end // always @ (posedge tx_clk or negedge tx_reset_n)
|
|
|
|
//Data mux, is controlled either by the mux select from the
|
//Data mux, is controlled either by the mux select from the
|
//primary data flow or from the FCS mux select. When PAD
|
//primary data flow or from the FCS mux select. When PAD
|
//data option is used bytes of all zeros are transmitted
|
//data option is used bytes of all zeros are transmitted
|
always @(fcs_active or app_tx_dt_in or tc2tx_fcs
|
always @(fcs_active or app_tx_dt_in or tc2tx_fcs
|
or send_bad_fcs or fcs_mux_select or
|
or send_bad_fcs or fcs_mux_select or
|
set_pad_byte or tx_fsm_dt_reg or send_pause_active or pause_index
|
set_pad_byte or tx_fsm_dt_reg )
|
or cf_mac_sa or cf2tx_pause_quanta)
|
|
begin
|
begin
|
if (send_pause_active)
|
if (!fcs_active && !set_pad_byte)
|
begin
|
|
case (pause_index)
|
|
5'd0 :
|
|
tx_byte = 8'h01;
|
|
5'd1 :
|
|
tx_byte = 8'h80;
|
|
5'd2 :
|
|
tx_byte = 8'hc2;
|
|
5'd3 :
|
|
tx_byte = 8'h00;
|
|
5'd4 :
|
|
tx_byte = 8'h00;
|
|
5'd5 :
|
|
tx_byte = 8'h01;
|
|
5'd6 :
|
|
tx_byte = cf_mac_sa[7:0];
|
|
5'd7 :
|
|
tx_byte = cf_mac_sa[15:8];
|
|
5'd8 :
|
|
tx_byte = cf_mac_sa[23:16];
|
|
5'd9 :
|
|
tx_byte = cf_mac_sa[31:24];
|
|
5'd10 :
|
|
tx_byte = cf_mac_sa[39:32];
|
|
5'd11 :
|
|
tx_byte = cf_mac_sa[47:40];
|
|
5'd12 :
|
|
tx_byte = 8'h88;
|
|
5'd13 :
|
|
tx_byte = 8'h08;
|
|
5'd14 :
|
|
tx_byte = 8'h00;
|
|
5'd15 :
|
|
tx_byte = 8'h01;
|
|
5'd16 :
|
|
tx_byte = cf2tx_pause_quanta[15:8];
|
|
5'd17 :
|
|
tx_byte = cf2tx_pause_quanta[7:0];
|
|
default :
|
|
tx_byte = 8'h00;
|
|
endcase // case (mux_select)
|
|
end
|
|
else if (!fcs_active && !set_pad_byte)
|
|
begin
|
begin
|
//primary data flow
|
//primary data flow
|
tx_byte = tx_fsm_dt_reg[7:0];
|
tx_byte = tx_fsm_dt_reg[7:0];
|
// $stop;
|
|
end // if (!fcs_active)
|
end // if (!fcs_active)
|
else if (fcs_active)
|
else if (fcs_active)
|
begin
|
begin
|
tx_byte = tc2tx_fcs[7:0];
|
tx_byte = tc2tx_fcs[7:0];
|
case (fcs_mux_select)
|
case (fcs_mux_select)
|