audrey
Newbie level 2
I am doing my project in the gigabit ethernet 802.3z protocol. I am using verilog as my language(xilinx) and i am using modelsim as my simulator. I have done the code in the module form as the transmitter and the receiver. The main aim of our project is to transmit the frame as per the format and then receive the data transmitted at the receiver output.
We are doing the testbench for the code we have implemented and we are supposed to use tasks so dat the user can input the data, source and destination address and the length of the data in bytes. We also need to ask the user wat type of frame he wants to transmit and hence call the appropriate task.
Please help me in implementing thees tasks as i am finding it very difficult. I need your help urgently. Thanking you.
This is my code
module rx_mac (
rx_clk,
reset_n,
rx_dv,
rx_error,
rx_data,
data,
rx_status_valid_n,
rx_status,
data_valid,
last_data,
eth_address
);
input rx_clk,
reset_n,
rx_dv,
rx_error;
input [3:0] rx_data;
input [47:0] eth_address;
output rx_status_valid_n,
data_valid,
last_data;
output [3:0] data;
output [15:0] rx_status;
wire SFD_start_detect,
SFD_detected,
FCS_start_check,
data_en,
address_match,
multicast,
broadcast,
crc_ok;
wire [3:0] data_tap,data;
rx_sm rx_sm (
.clk(rx_clk),
.reset_n(reset_n),
.rx_dv(rx_dv),
.rx_error(rx_error),
.SFD_detected(SFD_detected),
.address_match(address_match),
.multicast(multicast),
.broadcast(broadcast),
.crc_ok(crc_ok),
.SFD_start_detect(SFD_start_detect),
.FCS_start_check(FCS_start_check),
.data_en(data_en),
.data_valid(data_valid),
.last_data(last_data),
.rx_status_valid_n(rx_status_valid_n),
.rx_status(rx_status)
);
rx_buffer rx_buffer (
.clk(rx_clk),
.reset_n(reset_n),
.rx_data(rx_data),
.data_tap(data_tap),
.data(data),
.data_en(data_en)
);
SFD_detector rx_sfd (
.clk(rx_clk),
.reset_n(reset_n),
.data_tap(data_tap),
.SFD_start_detect(SFD_start_detect),
.SFD_detected(SFD_detected)
);
aml rx_aml (
.clk(rx_clk),
.reset_n(reset_n),
.data_tap(data_tap),
.eth_address(eth_address),
.SFD_detected(SFD_detected),
.address_match(address_match),
.multicast(multicast),
.broadcast(broadcast)
);
fcs_check rx_fcs (
.clk(rx_clk),
.reset_n(reset_n),
.FCS_start_check(FCS_start_check),
.data(data),
.crc_ok(crc_ok)
);
endmodule
`define INIT_COUNT (4'b0000)
`define END_COUNT (4'b1100)
`define BROADCAST (48'hFFFFFFFFFFFF)
`define ZERO_DA (48'h000000000000)
`define MULTICAST_SIGN (48'h010000000000)
module aml (
clk,
reset_n,
data_tap,
eth_address,
SFD_detected,
address_match,
broadcast,
multicast
);
input clk,
SFD_detected,
reset_n;
input [7:0] data_tap;
input [47:0] eth_address;
output address_match,
multicast,
broadcast;
reg address_match,
multicast,
broadcast,
start_count;
reg [1:0] state_AML;
reg [3:0] AML_count;
reg [7:0] data_tap_temp;
reg [47:0] DA;
parameter AML_IDLE = 2'b00,
AML_RUN = 2'b01,
AML_STOP = 2'b10;
always @(posedge clk or negedge reset_n)
if (!reset_n)
state_AML <= AML_IDLE;
else
case (state_AML)
AML_IDLE :
if (SFD_detected)
begin
start_count <= 1'b1;
state_AML <= AML_RUN;
end
else
begin
start_count <= 1'b0;
DA = `ZERO_DA;
state_AML <= AML_IDLE;
end
AML_RUN :
if (AML_count ==`END_COUNT)
state_AML <= AML_STOP;
else
begin
state_AML <= AML_RUN;
case(AML_count)
4'b0000 : DA[7:0] = data_tap_temp [7:0];
4'b0001 : DA[15:8] = data_tap_temp [7:0];
4'b0010 : DA[23:16] = data_tap_temp [7:0];
4'b0011 : DA[31:24] = data_tap_temp [7:0];
4'b0100 : DA[39:32] = data_tap_temp [7:0];
4'b0101 : DA[47:40] = data_tap_temp [7:0];
default :
DA = `ZERO_DA;
endcase
end
AML_STOP :
begin
start_count <= 1'b0;
state_AML <= AML_IDLE;
end
endcase
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
begin
address_match = 1'b0;
broadcast = 1'b0;
multicast = 1'b0;
end
else
if(state_AML == AML_IDLE)
begin
address_match = 1'b0;
broadcast = 1'b0;
multicast = 1'b0;
end
else
case(DA)
`BROADCAST :
begin
broadcast = 1'b1;
address_match = 1'b1;
end
eth_address :
address_match = 1'b1;
(eth_address | `MULTICAST_SIGN) :
begin
multicast = 1'b1;
address_match = 1'b1;
end
default :
address_match = 1'b0;
endcase
end
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
data_tap_temp <= 8'b00000000;
else
data_tap_temp <= data_tap;
end
always @(posedge clk or negedge reset_n)
if(!reset_n)
AML_count <= `INIT_COUNT;
else
if(!start_count)
AML_count <= `INIT_COUNT;
else
AML_count <= (AML_count + 1'b1);
endmodule
`define BUFFER_INIT_VALUE 32'hFFFFFFFF
`define CRCO_RESET 9'b000000000
`define CRC_NOT 9'b111111111
module fcs_check (
clk,
reset_n,
FCS_start_check,
data,
crc_ok
);
input FCS_start_check;
input [7:0] data;
input clk;
input reset_n;
output crc_ok;
reg crc_ok;
reg [31:0] crc_buffer;
function [31:0] count_crc;
input [3:0] d;
input [31:0] c;
reg [3:0] d;
reg [31:0] c;
reg [31:0] new_crc;
begin
new_crc[0] = d[3] ^ c[28];
new_crc[1] = d[2] ^ d[3] ^ c[28] ^ c[29];
new_crc[2] = d[1] ^ d[2] ^ d[3] ^ c[28] ^ c[29] ^ c[30];
new_crc[3] = d[0] ^ d[1] ^ d[2] ^ c[29] ^ c[30] ^ c[31];
new_crc[4] = d[0] ^ d[1] ^ d[3] ^ c[0] ^ c[28] ^ c[30] ^ c[31];
new_crc[5] = d[0] ^ d[2] ^ d[3] ^ c[1] ^ c[28] ^ c[29] ^ c[31];
new_crc[6] = d[1] ^ d[2] ^ c[2] ^ c[29] ^ c[30];
new_crc[7] = d[0] ^ d[1] ^ d[3] ^ c[3] ^ c[28] ^ c[30] ^ c[31];
new_crc[8] = d[0] ^ d[2] ^ d[3] ^ c[4] ^ c[28] ^ c[29] ^ c[31];
new_crc[9] = d[1] ^ d[2] ^ c[5] ^ c[29] ^ c[30];
new_crc[10] = d[0] ^ d[1] ^ d[3] ^ c[6] ^ c[28] ^ c[30] ^ c[31];
new_crc[11] = d[0] ^ d[2] ^ d[3] ^ c[7] ^ c[28] ^ c[29] ^ c[31];
new_crc[12] = d[1] ^ d[2] ^ d[3] ^ c[8] ^ c[28] ^ c[29] ^ c[30];
new_crc[13] = d[0] ^ d[1] ^ d[2] ^ c[9] ^ c[29] ^ c[30] ^ c[31];
new_crc[14] = d[0] ^ d[1] ^ c[10] ^ c[30] ^ c[31];
new_crc[15] = d[0] ^ c[11] ^ c[31];
new_crc[16] = d[3] ^ c[12] ^ c[28];
new_crc[17] = d[2] ^ c[13] ^ c[29];
new_crc[18] = d[1] ^ c[14] ^ c[30];
new_crc[19] = d[0] ^ c[15] ^ c[31];
new_crc[20] = c[16];
new_crc[21] = c[17];
new_crc[22] = d[3] ^ c[18] ^ c[28];
new_crc[23] = d[2] ^ d[3] ^ c[19] ^ c[28] ^ c[29];
new_crc[24] = d[1] ^ d[2] ^ c[20] ^ c[29] ^ c[30];
new_crc[25] = d[0] ^ d[1] ^ c[21] ^ c[30] ^ c[31];
new_crc[26] = d[0] ^ d[3] ^ c[22] ^ c[28] ^ c[31];
new_crc[27] = d[2] ^ c[23] ^ c[29];
new_crc[28] = d[1] ^ c[24] ^ c[30];
new_crc[29] = d[0] ^ c[25] ^ c[31];
new_crc[30] = c[26];
new_crc[31] = c[27];
count_crc = new_crc;
end
endfunction
always @(posedge clk)
begin
if (crc_buffer == 32'hc704dd7b) //:magic number
crc_ok <= 1'b1;
else
crc_ok <= 1'b0;
end
always @(posedge clk)
begin
if(!reset_n)
crc_buffer <= `BUFFER_INIT_VALUE;
else
if(FCS_start_check)
crc_buffer <= count_crc (data,crc_buffer);
else
crc_buffer <= `BUFFER_INIT_VALUE;
end
endmodule
module rx_buffer (
clk,
reset_n,
rx_data,
data_tap,
data,
data_en
);
input clk, data_en, reset_n;
input [7:0] rx_data;
output[7:0] data_tap,data;
reg [7:0] data_tap;
reg [7:0] data_temp;
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
data_tap <= 8'b00000000;
else
data_tap <= rx_data;
end
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
data_temp <= 8'b00000000;
else
data_temp <= data_tap;
end
assign data = data_en ? data_temp : 8'bzzzzzzzz;
endmodule
`define INITIAL_COUNT 12'b000000000000
`define MAX_COUNT 12'b101111011100
`define STATUS_RESET 16'b0000000000000000
`define STATUS_ERROR 15'b000000000000000
`define eo_DA 12'b000000001011
`define GET_CRC_OUT 12'b000000001101
`define CRCO_ZERO 9'b000000000
`define Rx_IDLE 4'b000
`define SFD_detect 4'b001
`define Rx_RUN 4'b010
`define Rx_HOLD 4'b011
`define Rx_STOP 4'b100
`define WRITE_STATUS 4'b101
`define HOLD1_STATUS 4'b110
`define HOLD2_STATUS 4'b111
module rx_sm (
clk,
reset_n,
rx_dv,
rx_error,
SFD_detected,
address_match,
multicast,
broadcast,
crc_ok,
SFD_start_detect,
data_en,
FCS_start_check,
last_data,
data_valid,
rx_status_valid_n,
rx_status
);
input clk,
reset_n,
rx_dv,
rx_error,
SFD_detected,
address_match,
multicast,
broadcast,
crc_ok;
output SFD_start_detect,
data_en,
FCS_start_check,
last_data,
data_valid,
rx_status_valid_n;
output [15:0] rx_status;
reg SFD_start_detect,
FCS_start_check,
data_en,
last_data,
broadcast_temp,
multicast_temp,
address_match_temp,
data_valid,
rx_error_temp,
sending_data_n_status,
rx_status_valid_n;
reg [3:0] rx_sm_state;
reg [12:0] nibble_count,
nibble_count_temp;
reg [15:0] rx_status;
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
rx_sm_state <= `Rx_IDLE;
else
if (rx_error)
begin
rx_error_temp <= 1'b1;
rx_sm_state <= `Rx_HOLD;
end
else
if((nibble_count_temp + 2'b10) == `MAX_COUNT)
begin
rx_error_temp <= 1'b1;
rx_sm_state <= `Rx_HOLD;
end
else
case (rx_sm_state)
`Rx_IDLE :
begin
if(rx_dv)
begin
rx_sm_state <= `SFD_detect;
SFD_start_detect <= 1'b1;
end
else
begin
SFD_start_detect <= 1'b0;
data_en <= 1'b0;
FCS_start_check <= 1'b0;
rx_status_valid_n <= 1'b1;
rx_status <= `STATUS_RESET;
last_data <= 1'b0;
data_valid <= 1'b0;
sending_data_n_status <= 1'b0;
rx_sm_state <= `Rx_IDLE;
rx_error_temp <= 1'b0;
end
end
`SFD_detect :
begin
if(!rx_dv)
rx_sm_state <= `Rx_HOLD;
else
if (SFD_detected)
begin
SFD_start_detect <= 1'b0;
FCS_start_check <= 1'b1;
data_valid <= 1'b1;
sending_data_n_status <= 1'b1;
data_en <= 1'b1;
rx_sm_state <= `Rx_RUN;
end
else
rx_sm_state <= `SFD_detect;
end
`Rx_RUN :
begin
if(!rx_dv)
begin
last_data <= 1'b1;
rx_sm_state <= `Rx_HOLD;
end
else
rx_sm_state <= `Rx_RUN;
end
`Rx_HOLD :
begin
last_data <= 1'b0;
data_valid <= 1'b0;
data_en <= 1'b0;
rx_sm_state <= `Rx_STOP;
end
`Rx_STOP :
begin
FCS_start_check <= 1'b0;
rx_sm_state <= `WRITE_STATUS;
end
`WRITE_STATUS :
begin
rx_status_valid_n <= 1'b0;
rx_status[0] <= rx_error_temp;
rx_status[1] <= address_match_temp;
rx_status[2] <= (broadcast_temp | multicast_temp);
rx_status[3] <= crc_ok;
rx_status[15:4] <= nibble_count + 1'b1;
rx_sm_state <= `HOLD1_STATUS;
end
`HOLD1_STATUS :
begin
rx_sm_state <= `HOLD2_STATUS;
end
`HOLD2_STATUS :
rx_sm_state <= `Rx_IDLE;
default :
rx_sm_state <= `Rx_IDLE;
endcase
end
always @(posedge clk or negedge reset_n)
begin
if(!reset_n)
nibble_count_temp <= `INITIAL_COUNT;
else
if(!data_en)
nibble_count_temp <= `INITIAL_COUNT;
else
nibble_count_temp <= (nibble_count_temp + 1'b1);
end
always @(posedge clk or negedge reset_n)
begin
if(!reset_n)
nibble_count <= `INITIAL_COUNT;
else
if(data_en)
nibble_count <= nibble_count_temp;
else
nibble_count <= nibble_count;
end
always @(posedge clk)
begin
if(!reset_n)
begin
broadcast_temp <= 1'b0;
multicast_temp <= 1'b0;
address_match_temp <= 1'b0;
end
else
if(!sending_data_n_status)
begin
broadcast_temp <= 1'b0;
multicast_temp <= 1'b0;
address_match_temp <= 1'b0;
end
else
if (address_match)
begin
broadcast_temp <= broadcast;
multicast_temp <= multicast;
address_match_temp <= address_match;
end
else
begin
broadcast_temp <= broadcast_temp;
multicast_temp <= multicast_temp;
address_match_temp <= address_match_temp;
end
end
endmodule
module SFD_detector (
clk,
reset_n,
data_tap,
SFD_start_detect,
SFD_detected
);
input clk, SFD_start_detect, reset_n;
input [3:0] data_tap;
output SFD_detected;
reg SFD_detected;
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
SFD_detected <= 1'b0;
else
if (!SFD_start_detect)
SFD_detected <= 1'b0;
else
begin
if (data_tap==4'b1101)
SFD_detected <= 1'b1;
else
SFD_detected <= 1'b0;
end
end
endmodule
module txethmac (
tx_data,
tx_sof,
tx_eof,
tx_underrun,
full_duplex,
reset_n,
crs,
coll,
tx_clk,
tx_data_used,
tx_done,
tx_abort,
tx_retransmit,
tx_status,
tx_status_valid_n,
txd,
tx_en,
tx_er
);
// from DMA
input [7:0] tx_data;
input tx_sof;
input tx_eof;
input tx_underrun;
input full_duplex;
input reset_n;
// from MII
input crs;
input coll;
input tx_clk;
// to MII
output [7:0] txd;
output tx_en;
output tx_er;
// to DMA
output tx_data_used;
output tx_done;
output tx_abort;
output tx_retransmit;
output [6:0] tx_status;
output tx_status_valid_n;
wire [7:0] data;
wire transmit_error;
wire transmit_enable;
wire compute_crc;
wire [7:0] crc;
wire [2:0] data_select;
wire transmit_available_p;
wire transmit_new_p;
wire excess_deferral;
wire transmit_preamble;
wire transmit_sfd;
wire [3:0] coll_attempt;
wire late_coll;
wire excessive_coll;
wire coll_event_p;
wire transmit_64byte;
wire transmit_fcs;
wire [11:0] count_length;
wire [3:0] count_fcs;
wire excessive_length;
wire [3:0] count_jam;
wire [9:0] random;
wire backoff_p;
wire start_backoff;
//instantiates modules
fifo_synch tx_1 (
.data(data),
.transmit_enable(transmit_enable),
.transmit_error(transmit_error),
.clk(tx_clk),
.txd(txd),
.tx_en(tx_en),
.tx_er(tx_er)
);
ifg_timer tx_2 (
.crs(crs),
.full_duplex(full_duplex),
.transmit_enable(transmit_enable),
.clk(tx_clk),
.reset_n(reset_n),
.transmit_available_p(transmit_available_p)
);
defer_counter tx_3 (
.transmit_available_p(transmit_available_p),
.transmit_new_p(transmit_new_p),
.clk(tx_clk),
.reset_n(reset_n),
.excess_deferral(excess_deferral)
);
frame_length_counter tx_4 (
.transmit_enable(transmit_enable),
.transmit_fcs(transmit_fcs),
.clk(tx_clk),
.reset_n(reset_n),
.count_length(count_length),
.count_fcs(count_fcs),
.excessive_length(excessive_length),
.transmit_64byte(transmit_64byte)
);
//coll_counter tx_5 (
//.transmit_new_p(transmit_new_p),
//.transmit_enable(transmit_enable),
// .transmit_preamble(transmit_preamble),
// .transmit_sfd(transmit_sfd),
// .transmit_64byte(transmit_64byte),
// .clk(tx_clk),
// .reset_n(reset_n),
// .coll(coll),
// .full_duplex(full_duplex),
// .coll_event_p(coll_event_p),
// .late_coll(late_coll),
// .excessive_coll(excessive_coll),
// .coll_attempt(coll_attempt)
// );
//random_number_gen tx_6 (
// .coll_attempt(coll_attempt),
// .clk(tx_clk),
// .reset_n(reset_n),
// .random(random)
// );
//backoff_timer tx_7 (
//.start_backoff(start_backoff),
//.random(random),
//.clk(tx_clk),
//.reset_n(reset_n),
//.backoff_p(backoff_p)
//);
//jam_timer tx_8 (
//.coll_event_p(coll_event_p),
//.clk(tx_clk),
//.reset_n(reset_n),
//.count_jam(count_jam)
//);
crc_gen tx_9 (
.compute_crc(compute_crc),
.data(data),
.clk(tx_clk),
.reset_n(reset_n),
.crc(crc)
);
data_mux tx_10(
.data_select(data_select),
.data_in(tx_data),
.crc(crc),
.data_out(data)
);
tx_state_machine tx_11 (
.tx_sof(tx_sof),
.tx_eof(tx_eof),
.tx_underrun(tx_underrun),
.clk(tx_clk),
.reset_n(reset_n),
.transmit_available_p(transmit_available_p),
.excess_deferral(excess_deferral),
.coll_event_p(coll_event_p),
.late_coll(late_coll),
.excessive_coll(excessive_coll),
.backoff_p(backoff_p),
.count_length(count_length),
.count_fcs(count_fcs),
.excessive_length(excessive_length),
.count_jam(count_jam),
.tx_data_used(tx_data_used),
.tx_done(tx_done),
.tx_abort(tx_abort),
.tx_retransmit(tx_retransmit),
.tx_status(tx_status),
.tx_status_valid_n(tx_status_valid_n),
.transmit_new_p(transmit_new_p),
.transmit_enable(transmit_enable),
.transmit_preamble(transmit_preamble),
.transmit_sfd(transmit_sfd),
.transmit_fcs(transmit_fcs),
.transmit_error(transmit_error),
.start_backoff(start_backoff),
.compute_crc(compute_crc),
.data_select(data_select)
);
`define CRC_INIT_VALUE (32'hFFFF_FFFF)
`define CRC_IDLE (2'b00)
`define CRC_RUN (2'b01)
`define CRC_STOP (2'b11)
module crc_gen (
compute_crc,
data,
clk,
reset_n,
crc
);
input compute_crc;
input [7:0] data;
input clk;
input reset_n;
output [7:0] crc;
reg [1:0] state_crc;
reg [31:0] crc_buffer;
reg [2:0] crc_end;
function [31:0] count_crc; // the first serial data bit is d [0]
input [3:0] d;
input [31:0] c;
reg [31:0] new_crc;
begin
new_crc[0] = d[3] ^ c[28];
new_crc[1] = d[2] ^ d[3] ^ c[28] ^ c[29];
new_crc[2] = d[1] ^ d[2] ^ d[3] ^ c[28] ^ c[29] ^ c[30];
new_crc[3] = d[0] ^ d[1] ^ d[2] ^ c[29] ^ c[30] ^ c[31];
new_crc[4] = d[0] ^ d[1] ^ d[3] ^ c[0] ^ c[28] ^ c[30] ^ c[31];
new_crc[5] = d[0] ^ d[2] ^ d[3] ^ c[1] ^ c[28] ^ c[29] ^ c[31];
new_crc[6] = d[1] ^ d[2] ^ c[2] ^ c[29] ^ c[30];
new_crc[7] = d[0] ^ d[1] ^ d[3] ^ c[3] ^ c[28] ^ c[30] ^ c[31];
new_crc[8] = d[0] ^ d[2] ^ d[3] ^ c[4] ^ c[28] ^ c[29] ^ c[31];
new_crc[9] = d[1] ^ d[2] ^ c[5] ^ c[29] ^ c[30];
new_crc[10] = d[0] ^ d[1] ^ d[3] ^ c[6] ^ c[28] ^ c[30] ^ c[31];
new_crc[11] = d[0] ^ d[2] ^ d[3] ^ c[7] ^ c[28] ^ c[29] ^ c[31];
new_crc[12] = d[1] ^ d[2] ^ d[3] ^ c[8] ^ c[28] ^ c[29] ^ c[30];
new_crc[13] = d[0] ^ d[1] ^ d[2] ^ c[9] ^ c[29] ^ c[30] ^ c[31];
new_crc[14] = d[0] ^ d[1] ^ c[10] ^ c[30] ^ c[31];
new_crc[15] = d[0] ^ c[11] ^ c[31];
new_crc[16] = d[3] ^ c[12] ^ c[28];
new_crc[17] = d[2] ^ c[13] ^ c[29];
new_crc[18] = d[1] ^ c[14] ^ c[30];
new_crc[19] = d[0] ^ c[15] ^ c[31];
new_crc[20] = c[16];
new_crc[21] = c[17];
new_crc[22] = d[3] ^ c[18] ^ c[28];
new_crc[23] = d[2] ^ d[3] ^ c[19] ^ c[28] ^ c[29];
new_crc[24] = d[1] ^ d[2] ^ c[20] ^ c[29] ^ c[30];
new_crc[25] = d[0] ^ d[1] ^ c[21] ^ c[30] ^ c[31];
new_crc[26] = d[0] ^ d[3] ^ c[22] ^ c[28] ^ c[31];
new_crc[27] = d[2] ^ c[23] ^ c[29];
new_crc[28] = d[1] ^ c[24] ^ c[30];
new_crc[29] = d[0] ^ c[25] ^ c[31];
new_crc[30] = c[26];
new_crc[31] = c[27];
count_crc = new_crc;
end
endfunction
assign crc [7] = ~ crc_buffer [24];
assign crc [6] = ~ crc_buffer [25];
assign crc [5] = ~ crc_buffer [26];
assign crc [4] = ~ crc_buffer [27];
assign crc [3] = ~ crc_buffer [28];
assign crc [2] = ~ crc_buffer [29];
assign crc [1] = ~ crc_buffer [30];
assign crc [0] = ~ crc_buffer [31];
always @(posedge clk or negedge reset_n)
if (!reset_n)
state_crc <= `CRC_IDLE;
else
case (state_crc)
`CRC_IDLE : if (compute_crc)
begin
state_crc <= `CRC_RUN;
crc_buffer <= count_crc (data,`CRC_INIT_VALUE);
end
else
begin
state_crc <= `CRC_IDLE;
crc_buffer <= 32'h0000_0000;
crc_end <= 3'd0;
end
`CRC_RUN : if (!compute_crc)
begin
state_crc <= `CRC_STOP;
crc_buffer <= crc_buffer << 8;
end
else
begin
state_crc <= `CRC_RUN;
crc_buffer <= count_crc (data,crc_buffer);
end
`CRC_STOP : if (crc_end == 3'110)
begin
state_crc <= `CRC_IDLE;
crc_buffer <= 32'h0000_0000;
end
else
begin
state_crc <= `CRC_STOP;
crc_buffer <= crc_buffer << 4;
crc_end <= crc_end + 1'b1;
end
endcase
endmodule
`define PATTERN_PREAMBLE (8'b01010101)
`define PATTERN_SFD (8'b11010101)
module data_mux (
data_select,
data_in,
crc,
data_out,
count_length
);
input [2:0] data_select;
input [7:0] data_in;
input [7:0] crc;
input [7:0] count_length ;
output [7:0] data_out;
reg [7:0] data_out;
always @(data_select or data_in or crc)
case (data_select)
3'b000 : data_out = data_in;
3'b001 : data_out = `PATTERN_PREAMBLE;
3'b010 : data_out = `PATTERN_SFD;
3'b011 : data_out = crc;
3'b100 : data_out = src_add;
3'b101 : data_out = dst_add;
3'b110 : data_out = count_length;
default : data_out = 8'h00;
endcase
endmodule
module fifo_synch (
data,
transmit_enable,
transmit_error,
clk,
txd,
tx_en,
tx_er
);
input [7:0] data;
input transmit_enable;
input transmit_error;
input clk;
output [7:0] txd;
output tx_en;
output tx_er;
reg [7:0] txd;
reg tx_en;
reg tx_er;
always @(posedge clk)
if (transmit_enable)
begin
txd <= data;
tx_en <= 1'b1;
tx_er <= transmit_error;
end
else
begin
txd <= 8'h00;
tx_en <= 1'b0;
tx_er <= 1'b0;
end
endmodule
`define COUNT_LENGTH_IDLE (2'b00)
`define COUNT_LENGTH_RUN (2'b01)
`define COUNT_LENGTH_FCS (2'b11)
`define MIN_LENGTH (12'd144)
`define MAX_LENGTH (12'd3052)
module frame_length_counter (
transmit_enable,
transmit_fcs,
clk,
reset_n,
count_length,
count_fcs,
excessive_length,
transmit_64byte
);
input transmit_enable;
input transmit_fcs;
input clk;
input reset_n;
output [11:0] count_length;
output [3:0] count_fcs;
output excessive_length;
output transmit_64byte;
reg [11:0] count_length;
reg [3:0] count_fcs;
reg excessive_length;
reg transmit_64byte;
reg [1:0] state_length;
function [11:0] inc_length;
input [11:0] count_length;
begin
inc_length = count_length + 1'b1;
end
endfunction
always @(posedge clk or negedge reset_n)
if (!reset_n)
begin
state_length <= `COUNT_LENGTH_IDLE;
count_length <= 12'd0;
count_fcs <= 4'd0;
end
else
case (state_length)
`COUNT_LENGTH_IDLE : if (transmit_enable)
begin
state_length <= `COUNT_LENGTH_RUN;
count_length <= 12'd1;
end
else
state_length <= `COUNT_LENGTH_IDLE;
`COUNT_LENGTH_RUN : if (!transmit_enable)
state_length <= `COUNT_LENGTH_IDLE;
else
if (transmit_fcs)
begin
state_length <= `COUNT_LENGTH_FCS;
count_length <= inc_length(count_length);
count_fcs <= 4'd1;
end
else
begin
state_length <= `COUNT_LENGTH_RUN;
count_length <= inc_length(count_length);
end
`COUNT_LENGTH_FCS : if (!transmit_enable)
state_length <= `COUNT_LENGTH_IDLE;
else
begin
state_length <= `COUNT_LENGTH_FCS;
count_length <= inc_length(count_length);
count_fcs <= (count_fcs + 1'b1);
end
endcase
always @(count_length)
begin
transmit_64byte = (count_length > `MIN_LENGTH-1) ? 1'b1 : 1'b0;
excessive_length = (count_length > `MAX_LENGTH-1) ? 1'b1 : 1'b0;
end
endmodule
`define IFG_LENGTH_1 (5'd15)
`define IFG_LENGTH_2 (5'd22)
`define IFG_IDLE (1'b0)
`define IFG_RUN (1'b1)
module ifg_timer (
crs,
full_duplex,
transmit_enable,
clk,
reset_n,
transmit_available_p
);
input crs;
input full_duplex;
input transmit_enable;
input clk;
input reset_n;
output transmit_available_p;
reg transmit_available_p;
reg [4:0] count_ifg;
reg state_ifg;
function [4:0] inc_ifg;
input [4:0] count_ifg;
begin
inc_ifg = count_ifg + 1'b1;
end
endfunction
always @(posedge clk or negedge reset_n)
if (!reset_n)
state_ifg <= `IFG_IDLE;
else
if (full_duplex)
case (state_ifg)
`IFG_IDLE : if (!transmit_enable)
begin
state_ifg <= `IFG_RUN;
count_ifg <= 5'd1;
transmit_available_p <= 1'b0;
end
else
begin
state_ifg <= `IFG_IDLE;
count_ifg <= 5'd0;
transmit_available_p <= 1'b0;
end
`IFG_RUN : if (transmit_enable)
state_ifg <= `IFG_IDLE;
else
if (count_ifg == `IFG_LENGTH_2-1)
begin
state_ifg <= `IFG_IDLE;
transmit_available_p <= 1'b1;
end
else
begin
state_ifg <= `IFG_RUN;
count_ifg <= inc_ifg(count_ifg);
end
endcase
else
case (state_ifg)
`IFG_IDLE : if (!crs)
begin
state_ifg <= `IFG_RUN;
count_ifg <= 5'd1;
transmit_available_p <= 1'b0;
end
else
begin
state_ifg <= `IFG_IDLE;
count_ifg <= 5'd0;
transmit_available_p <= 1'b0;
end
`IFG_RUN : if (crs && (count_ifg <= `IFG_LENGTH_1-1))
state_ifg <= `IFG_IDLE;
else
if (count_ifg == `IFG_LENGTH_2-1)
begin
state_ifg <= `IFG_IDLE;
transmit_available_p <= 1'b1;
end
else
begin
state_ifg <= `IFG_RUN;
count_ifg <= inc_ifg(count_ifg);
end
endcase
endmodule
`define TRANSMIT_IDLE (4'b0000)
`define NEW_TRANSMIT (4'b0001)
`define WAIT_TRANSMIT (4'b0011)
`define TRANSMIT_PREAMBLE (4'b0010)
`define TRANSMIT_SFD (4'b0110)
`define TRANSMIT_DATA (4'b0111)
`define TRANSMIT_PAD (4'b0101)
`define TRANSMIT_FCS (4'b0100)
`define WAIT_DONE (4'b1100)
`define TRANSMIT_DONE (4'b1101)
`define TRANSMIT_JAM (4'b1111)
`define WAIT_BACKOFF (4'b1110)
`define WAIT_ABORT (4'b1010)
`define TRANSMIT_ABORT (4'b1011)
`define WRITE_STATUS (4'b1001)
//`define (4'b1000)
`define PREAMBLE_LENGTH (12'd15)
`define SFD_LENGTH (12'd1)
`define DATA_LENGTH (12'd120)
`define FCS_LENGTH (4'd8)
`define JAM_LENGTH (4'd8)
`define WIDTH_STATUS 7
module tx_state_machine (
tx_sof,
tx_eof,
tx_underrun,
clk,
reset_n,
transmit_available_p,
excess_deferral,
coll_event_p,
late_coll,
excessive_coll,
backoff_p,
count_length,
count_fcs,
excessive_length,
count_jam,
tx_data_used,
tx_done,
tx_abort,
tx_retransmit,
tx_status,
tx_status_valid_n,
transmit_new_p,
transmit_enable,
transmit_preamble,
transmit_sfd,
transmit_fcs,
transmit_error,
start_backoff,
compute_crc,
data_select
);
input tx_sof;
input tx_eof;
input tx_underrun;
input clk;
input reset_n;
input transmit_available_p;
input excess_deferral;
input excessive_length;
input excessive_coll;
input late_coll;
input coll_event_p;
input backoff_p;
input [11:0] count_length;
input [3:0] count_fcs;
input [3:0] count_jam;
output tx_data_used;
output tx_done;
output tx_abort;
output tx_retransmit;
output [`WIDTH_STATUS-1:0] tx_status;
output tx_status_valid_n;
output transmit_new_p;
output transmit_enable;
output transmit_preamble;
output transmit_sfd;
output transmit_fcs;
output transmit_error;
output start_backoff;
output compute_crc;
output [2:0] data_select;
reg tx_data_used;
reg tx_done;
reg tx_abort;
reg tx_retransmit;
// reg [`WIDTH_STATUS-1:0] tx_status;
reg tx_status_valid_n;
reg transmit_new_p;
reg transmit_enable;
reg transmit_preamble;
reg transmit_sfd;
reg transmit_fcs;
reg transmit_error;
reg start_backoff;
reg compute_crc;
reg [2:0] data_select;
reg [3:0] current_tx_state;
reg [3:0] next_tx_state;
always @(posedge clk or negedge reset_n)
if (!reset_n)
current_tx_state <= `TRANSMIT_IDLE;
else
current_tx_state <= next_tx_state;
always @(current_tx_state or tx_sof or tx_eof or tx_underrun or
transmit_available_p or excess_deferral or excessive_length or
excessive_coll or late_coll or coll_event_p or backoff_p or
count_length or count_fcs or count_jam)
case (current_tx_state)
`TRANSMIT_IDLE : if (tx_sof)
next_tx_state = `NEW_TRANSMIT;
else
next_tx_state = `TRANSMIT_IDLE;
`NEW_TRANSMIT : if (!tx_sof)
next_tx_state = `TRANSMIT_IDLE;
else
next_tx_state = `WAIT_TRANSMIT;
`WAIT_TRANSMIT : if (!tx_sof)
next_tx_state = `TRANSMIT_IDLE;
else
if (excess_deferral)
next_tx_state = `WAIT_ABORT;
else
if (transmit_available_p)
next_tx_state = `TRANSMIT_PREAMBLE;
else
next_tx_state = `WAIT_TRANSMIT;
`TRANSMIT_PREAMBLE : if (!tx_sof)
next_tx_state = `TRANSMIT_IDLE;
else
if (count_length == `PREAMBLE_LENGTH-1)
next_tx_state = `TRANSMIT_SFD;
else
next_tx_state = `TRANSMIT_PREAMBLE;
`TRANSMIT_SFD : if (!tx_sof)
next_tx_state = `TRANSMIT_IDLE;
else
next_tx_state = `TRANSMIT_DATA;
`TRANSMIT_DATA : if (coll_event_p)
next_tx_state = `TRANSMIT_JAM;
else
if (tx_underrun || excessive_length)
next_tx_state = `WAIT_ABORT;
else
if (tx_eof)
begin
if (count_length < (`PREAMBLE_LENGTH+`SFD_LENGTH+`DATA_LENGTH-1))
next_tx_state = `TRANSMIT_PAD;
else
next_tx_state = `TRANSMIT_FCS;
end
else
next_tx_state = `TRANSMIT_DATA;
`TRANSMIT_PAD : if (coll_event_p)
next_tx_state = `TRANSMIT_JAM;
else
if (count_length == (`PREAMBLE_LENGTH+`SFD_LENGTH+`DATA_LENGTH-1))
next_tx_state = `TRANSMIT_FCS;
else
next_tx_state = `TRANSMIT_PAD;
`TRANSMIT_FCS : if (coll_event_p)
next_tx_state = `TRANSMIT_JAM;
else
if (excessive_length)
next_tx_state = `WAIT_ABORT;
else
if (count_fcs == `FCS_LENGTH-1)
next_tx_state = `WAIT_DONE;
else
next_tx_state = `TRANSMIT_FCS;
`TRANSMIT_JAM : if (count_jam == `JAM_LENGTH-3)
begin
if (late_coll || excessive_coll)
next_tx_state = `WAIT_ABORT;
else
next_tx_state = `WAIT_BACKOFF;
end
else
next_tx_state = `TRANSMIT_JAM;
`WAIT_BACKOFF : if (backoff_p)
next_tx_state = `WAIT_TRANSMIT;
else
next_tx_state = `WAIT_BACKOFF;
`WAIT_DONE : if (coll_event_p)
next_tx_state = `TRANSMIT_JAM;
else
if (excessive_length)
next_tx_state = `WAIT_ABORT;
else
next_tx_state = `TRANSMIT_DONE;
`TRANSMIT_DONE : next_tx_state = `WRITE_STATUS;
`WAIT_ABORT : next_tx_state = `TRANSMIT_ABORT;
`TRANSMIT_ABORT : next_tx_state = `WRITE_STATUS;
`WRITE_STATUS : next_tx_state = `TRANSMIT_IDLE;
default : next_tx_state = `TRANSMIT_IDLE;
endcase
always @(current_tx_state)
case (current_tx_state)
`TRANSMIT_IDLE :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`NEW_TRANSMIT :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b1;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`WAIT_TRANSMIT :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_PREAMBLE :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b1;
transmit_preamble = 1'b1;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b001;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_SFD :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b1;
transmit_preamble = 1'b0;
transmit_sfd = 1'b1;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b010;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_DATA :
begin
tx_data_used = 1'b1;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b1;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b1;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_PAD :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b1;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b001;
compute_crc = 1'b1;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_FCS :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b1;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b1;
start_backoff = 1'b0;
data_select = 3'b011;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`WAIT_DONE :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_DONE :
begin
tx_data_used = 1'b0;
tx_done = 1'b1;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_JAM :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b1;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b001;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`WAIT_BACKOFF :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b1;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b1;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`WAIT_ABORT :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_ABORT :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b1;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`WRITE_STATUS :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b0;
end
default :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
endcase
assign tx_status [0] = excess_deferral;
assign tx_status [1] = late_coll;
assign tx_status [2] = excessive_coll;
assign tx_status [3] = 1'b0;
assign tx_status [4] = excessive_length;
assign tx_status [5] = (excess_deferral | late_coll | excessive_coll |
tx_underrun | excessive_length);
assign tx_status [6] = ~(excess_deferral | late_coll | excessive_coll |
tx_underrun | excessive_length);
always @(posedge clk)
if (tx_underrun)
transmit_error <= 1'b1;
else
transmit_error <= 1'b0;
endmodule
We are doing the testbench for the code we have implemented and we are supposed to use tasks so dat the user can input the data, source and destination address and the length of the data in bytes. We also need to ask the user wat type of frame he wants to transmit and hence call the appropriate task.
Please help me in implementing thees tasks as i am finding it very difficult. I need your help urgently. Thanking you.
This is my code
module rx_mac (
rx_clk,
reset_n,
rx_dv,
rx_error,
rx_data,
data,
rx_status_valid_n,
rx_status,
data_valid,
last_data,
eth_address
);
input rx_clk,
reset_n,
rx_dv,
rx_error;
input [3:0] rx_data;
input [47:0] eth_address;
output rx_status_valid_n,
data_valid,
last_data;
output [3:0] data;
output [15:0] rx_status;
wire SFD_start_detect,
SFD_detected,
FCS_start_check,
data_en,
address_match,
multicast,
broadcast,
crc_ok;
wire [3:0] data_tap,data;
rx_sm rx_sm (
.clk(rx_clk),
.reset_n(reset_n),
.rx_dv(rx_dv),
.rx_error(rx_error),
.SFD_detected(SFD_detected),
.address_match(address_match),
.multicast(multicast),
.broadcast(broadcast),
.crc_ok(crc_ok),
.SFD_start_detect(SFD_start_detect),
.FCS_start_check(FCS_start_check),
.data_en(data_en),
.data_valid(data_valid),
.last_data(last_data),
.rx_status_valid_n(rx_status_valid_n),
.rx_status(rx_status)
);
rx_buffer rx_buffer (
.clk(rx_clk),
.reset_n(reset_n),
.rx_data(rx_data),
.data_tap(data_tap),
.data(data),
.data_en(data_en)
);
SFD_detector rx_sfd (
.clk(rx_clk),
.reset_n(reset_n),
.data_tap(data_tap),
.SFD_start_detect(SFD_start_detect),
.SFD_detected(SFD_detected)
);
aml rx_aml (
.clk(rx_clk),
.reset_n(reset_n),
.data_tap(data_tap),
.eth_address(eth_address),
.SFD_detected(SFD_detected),
.address_match(address_match),
.multicast(multicast),
.broadcast(broadcast)
);
fcs_check rx_fcs (
.clk(rx_clk),
.reset_n(reset_n),
.FCS_start_check(FCS_start_check),
.data(data),
.crc_ok(crc_ok)
);
endmodule
`define INIT_COUNT (4'b0000)
`define END_COUNT (4'b1100)
`define BROADCAST (48'hFFFFFFFFFFFF)
`define ZERO_DA (48'h000000000000)
`define MULTICAST_SIGN (48'h010000000000)
module aml (
clk,
reset_n,
data_tap,
eth_address,
SFD_detected,
address_match,
broadcast,
multicast
);
input clk,
SFD_detected,
reset_n;
input [7:0] data_tap;
input [47:0] eth_address;
output address_match,
multicast,
broadcast;
reg address_match,
multicast,
broadcast,
start_count;
reg [1:0] state_AML;
reg [3:0] AML_count;
reg [7:0] data_tap_temp;
reg [47:0] DA;
parameter AML_IDLE = 2'b00,
AML_RUN = 2'b01,
AML_STOP = 2'b10;
always @(posedge clk or negedge reset_n)
if (!reset_n)
state_AML <= AML_IDLE;
else
case (state_AML)
AML_IDLE :
if (SFD_detected)
begin
start_count <= 1'b1;
state_AML <= AML_RUN;
end
else
begin
start_count <= 1'b0;
DA = `ZERO_DA;
state_AML <= AML_IDLE;
end
AML_RUN :
if (AML_count ==`END_COUNT)
state_AML <= AML_STOP;
else
begin
state_AML <= AML_RUN;
case(AML_count)
4'b0000 : DA[7:0] = data_tap_temp [7:0];
4'b0001 : DA[15:8] = data_tap_temp [7:0];
4'b0010 : DA[23:16] = data_tap_temp [7:0];
4'b0011 : DA[31:24] = data_tap_temp [7:0];
4'b0100 : DA[39:32] = data_tap_temp [7:0];
4'b0101 : DA[47:40] = data_tap_temp [7:0];
default :
DA = `ZERO_DA;
endcase
end
AML_STOP :
begin
start_count <= 1'b0;
state_AML <= AML_IDLE;
end
endcase
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
begin
address_match = 1'b0;
broadcast = 1'b0;
multicast = 1'b0;
end
else
if(state_AML == AML_IDLE)
begin
address_match = 1'b0;
broadcast = 1'b0;
multicast = 1'b0;
end
else
case(DA)
`BROADCAST :
begin
broadcast = 1'b1;
address_match = 1'b1;
end
eth_address :
address_match = 1'b1;
(eth_address | `MULTICAST_SIGN) :
begin
multicast = 1'b1;
address_match = 1'b1;
end
default :
address_match = 1'b0;
endcase
end
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
data_tap_temp <= 8'b00000000;
else
data_tap_temp <= data_tap;
end
always @(posedge clk or negedge reset_n)
if(!reset_n)
AML_count <= `INIT_COUNT;
else
if(!start_count)
AML_count <= `INIT_COUNT;
else
AML_count <= (AML_count + 1'b1);
endmodule
`define BUFFER_INIT_VALUE 32'hFFFFFFFF
`define CRCO_RESET 9'b000000000
`define CRC_NOT 9'b111111111
module fcs_check (
clk,
reset_n,
FCS_start_check,
data,
crc_ok
);
input FCS_start_check;
input [7:0] data;
input clk;
input reset_n;
output crc_ok;
reg crc_ok;
reg [31:0] crc_buffer;
function [31:0] count_crc;
input [3:0] d;
input [31:0] c;
reg [3:0] d;
reg [31:0] c;
reg [31:0] new_crc;
begin
new_crc[0] = d[3] ^ c[28];
new_crc[1] = d[2] ^ d[3] ^ c[28] ^ c[29];
new_crc[2] = d[1] ^ d[2] ^ d[3] ^ c[28] ^ c[29] ^ c[30];
new_crc[3] = d[0] ^ d[1] ^ d[2] ^ c[29] ^ c[30] ^ c[31];
new_crc[4] = d[0] ^ d[1] ^ d[3] ^ c[0] ^ c[28] ^ c[30] ^ c[31];
new_crc[5] = d[0] ^ d[2] ^ d[3] ^ c[1] ^ c[28] ^ c[29] ^ c[31];
new_crc[6] = d[1] ^ d[2] ^ c[2] ^ c[29] ^ c[30];
new_crc[7] = d[0] ^ d[1] ^ d[3] ^ c[3] ^ c[28] ^ c[30] ^ c[31];
new_crc[8] = d[0] ^ d[2] ^ d[3] ^ c[4] ^ c[28] ^ c[29] ^ c[31];
new_crc[9] = d[1] ^ d[2] ^ c[5] ^ c[29] ^ c[30];
new_crc[10] = d[0] ^ d[1] ^ d[3] ^ c[6] ^ c[28] ^ c[30] ^ c[31];
new_crc[11] = d[0] ^ d[2] ^ d[3] ^ c[7] ^ c[28] ^ c[29] ^ c[31];
new_crc[12] = d[1] ^ d[2] ^ d[3] ^ c[8] ^ c[28] ^ c[29] ^ c[30];
new_crc[13] = d[0] ^ d[1] ^ d[2] ^ c[9] ^ c[29] ^ c[30] ^ c[31];
new_crc[14] = d[0] ^ d[1] ^ c[10] ^ c[30] ^ c[31];
new_crc[15] = d[0] ^ c[11] ^ c[31];
new_crc[16] = d[3] ^ c[12] ^ c[28];
new_crc[17] = d[2] ^ c[13] ^ c[29];
new_crc[18] = d[1] ^ c[14] ^ c[30];
new_crc[19] = d[0] ^ c[15] ^ c[31];
new_crc[20] = c[16];
new_crc[21] = c[17];
new_crc[22] = d[3] ^ c[18] ^ c[28];
new_crc[23] = d[2] ^ d[3] ^ c[19] ^ c[28] ^ c[29];
new_crc[24] = d[1] ^ d[2] ^ c[20] ^ c[29] ^ c[30];
new_crc[25] = d[0] ^ d[1] ^ c[21] ^ c[30] ^ c[31];
new_crc[26] = d[0] ^ d[3] ^ c[22] ^ c[28] ^ c[31];
new_crc[27] = d[2] ^ c[23] ^ c[29];
new_crc[28] = d[1] ^ c[24] ^ c[30];
new_crc[29] = d[0] ^ c[25] ^ c[31];
new_crc[30] = c[26];
new_crc[31] = c[27];
count_crc = new_crc;
end
endfunction
always @(posedge clk)
begin
if (crc_buffer == 32'hc704dd7b) //:magic number
crc_ok <= 1'b1;
else
crc_ok <= 1'b0;
end
always @(posedge clk)
begin
if(!reset_n)
crc_buffer <= `BUFFER_INIT_VALUE;
else
if(FCS_start_check)
crc_buffer <= count_crc (data,crc_buffer);
else
crc_buffer <= `BUFFER_INIT_VALUE;
end
endmodule
module rx_buffer (
clk,
reset_n,
rx_data,
data_tap,
data,
data_en
);
input clk, data_en, reset_n;
input [7:0] rx_data;
output[7:0] data_tap,data;
reg [7:0] data_tap;
reg [7:0] data_temp;
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
data_tap <= 8'b00000000;
else
data_tap <= rx_data;
end
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
data_temp <= 8'b00000000;
else
data_temp <= data_tap;
end
assign data = data_en ? data_temp : 8'bzzzzzzzz;
endmodule
`define INITIAL_COUNT 12'b000000000000
`define MAX_COUNT 12'b101111011100
`define STATUS_RESET 16'b0000000000000000
`define STATUS_ERROR 15'b000000000000000
`define eo_DA 12'b000000001011
`define GET_CRC_OUT 12'b000000001101
`define CRCO_ZERO 9'b000000000
`define Rx_IDLE 4'b000
`define SFD_detect 4'b001
`define Rx_RUN 4'b010
`define Rx_HOLD 4'b011
`define Rx_STOP 4'b100
`define WRITE_STATUS 4'b101
`define HOLD1_STATUS 4'b110
`define HOLD2_STATUS 4'b111
module rx_sm (
clk,
reset_n,
rx_dv,
rx_error,
SFD_detected,
address_match,
multicast,
broadcast,
crc_ok,
SFD_start_detect,
data_en,
FCS_start_check,
last_data,
data_valid,
rx_status_valid_n,
rx_status
);
input clk,
reset_n,
rx_dv,
rx_error,
SFD_detected,
address_match,
multicast,
broadcast,
crc_ok;
output SFD_start_detect,
data_en,
FCS_start_check,
last_data,
data_valid,
rx_status_valid_n;
output [15:0] rx_status;
reg SFD_start_detect,
FCS_start_check,
data_en,
last_data,
broadcast_temp,
multicast_temp,
address_match_temp,
data_valid,
rx_error_temp,
sending_data_n_status,
rx_status_valid_n;
reg [3:0] rx_sm_state;
reg [12:0] nibble_count,
nibble_count_temp;
reg [15:0] rx_status;
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
rx_sm_state <= `Rx_IDLE;
else
if (rx_error)
begin
rx_error_temp <= 1'b1;
rx_sm_state <= `Rx_HOLD;
end
else
if((nibble_count_temp + 2'b10) == `MAX_COUNT)
begin
rx_error_temp <= 1'b1;
rx_sm_state <= `Rx_HOLD;
end
else
case (rx_sm_state)
`Rx_IDLE :
begin
if(rx_dv)
begin
rx_sm_state <= `SFD_detect;
SFD_start_detect <= 1'b1;
end
else
begin
SFD_start_detect <= 1'b0;
data_en <= 1'b0;
FCS_start_check <= 1'b0;
rx_status_valid_n <= 1'b1;
rx_status <= `STATUS_RESET;
last_data <= 1'b0;
data_valid <= 1'b0;
sending_data_n_status <= 1'b0;
rx_sm_state <= `Rx_IDLE;
rx_error_temp <= 1'b0;
end
end
`SFD_detect :
begin
if(!rx_dv)
rx_sm_state <= `Rx_HOLD;
else
if (SFD_detected)
begin
SFD_start_detect <= 1'b0;
FCS_start_check <= 1'b1;
data_valid <= 1'b1;
sending_data_n_status <= 1'b1;
data_en <= 1'b1;
rx_sm_state <= `Rx_RUN;
end
else
rx_sm_state <= `SFD_detect;
end
`Rx_RUN :
begin
if(!rx_dv)
begin
last_data <= 1'b1;
rx_sm_state <= `Rx_HOLD;
end
else
rx_sm_state <= `Rx_RUN;
end
`Rx_HOLD :
begin
last_data <= 1'b0;
data_valid <= 1'b0;
data_en <= 1'b0;
rx_sm_state <= `Rx_STOP;
end
`Rx_STOP :
begin
FCS_start_check <= 1'b0;
rx_sm_state <= `WRITE_STATUS;
end
`WRITE_STATUS :
begin
rx_status_valid_n <= 1'b0;
rx_status[0] <= rx_error_temp;
rx_status[1] <= address_match_temp;
rx_status[2] <= (broadcast_temp | multicast_temp);
rx_status[3] <= crc_ok;
rx_status[15:4] <= nibble_count + 1'b1;
rx_sm_state <= `HOLD1_STATUS;
end
`HOLD1_STATUS :
begin
rx_sm_state <= `HOLD2_STATUS;
end
`HOLD2_STATUS :
rx_sm_state <= `Rx_IDLE;
default :
rx_sm_state <= `Rx_IDLE;
endcase
end
always @(posedge clk or negedge reset_n)
begin
if(!reset_n)
nibble_count_temp <= `INITIAL_COUNT;
else
if(!data_en)
nibble_count_temp <= `INITIAL_COUNT;
else
nibble_count_temp <= (nibble_count_temp + 1'b1);
end
always @(posedge clk or negedge reset_n)
begin
if(!reset_n)
nibble_count <= `INITIAL_COUNT;
else
if(data_en)
nibble_count <= nibble_count_temp;
else
nibble_count <= nibble_count;
end
always @(posedge clk)
begin
if(!reset_n)
begin
broadcast_temp <= 1'b0;
multicast_temp <= 1'b0;
address_match_temp <= 1'b0;
end
else
if(!sending_data_n_status)
begin
broadcast_temp <= 1'b0;
multicast_temp <= 1'b0;
address_match_temp <= 1'b0;
end
else
if (address_match)
begin
broadcast_temp <= broadcast;
multicast_temp <= multicast;
address_match_temp <= address_match;
end
else
begin
broadcast_temp <= broadcast_temp;
multicast_temp <= multicast_temp;
address_match_temp <= address_match_temp;
end
end
endmodule
module SFD_detector (
clk,
reset_n,
data_tap,
SFD_start_detect,
SFD_detected
);
input clk, SFD_start_detect, reset_n;
input [3:0] data_tap;
output SFD_detected;
reg SFD_detected;
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
SFD_detected <= 1'b0;
else
if (!SFD_start_detect)
SFD_detected <= 1'b0;
else
begin
if (data_tap==4'b1101)
SFD_detected <= 1'b1;
else
SFD_detected <= 1'b0;
end
end
endmodule
module txethmac (
tx_data,
tx_sof,
tx_eof,
tx_underrun,
full_duplex,
reset_n,
crs,
coll,
tx_clk,
tx_data_used,
tx_done,
tx_abort,
tx_retransmit,
tx_status,
tx_status_valid_n,
txd,
tx_en,
tx_er
);
// from DMA
input [7:0] tx_data;
input tx_sof;
input tx_eof;
input tx_underrun;
input full_duplex;
input reset_n;
// from MII
input crs;
input coll;
input tx_clk;
// to MII
output [7:0] txd;
output tx_en;
output tx_er;
// to DMA
output tx_data_used;
output tx_done;
output tx_abort;
output tx_retransmit;
output [6:0] tx_status;
output tx_status_valid_n;
wire [7:0] data;
wire transmit_error;
wire transmit_enable;
wire compute_crc;
wire [7:0] crc;
wire [2:0] data_select;
wire transmit_available_p;
wire transmit_new_p;
wire excess_deferral;
wire transmit_preamble;
wire transmit_sfd;
wire [3:0] coll_attempt;
wire late_coll;
wire excessive_coll;
wire coll_event_p;
wire transmit_64byte;
wire transmit_fcs;
wire [11:0] count_length;
wire [3:0] count_fcs;
wire excessive_length;
wire [3:0] count_jam;
wire [9:0] random;
wire backoff_p;
wire start_backoff;
//instantiates modules
fifo_synch tx_1 (
.data(data),
.transmit_enable(transmit_enable),
.transmit_error(transmit_error),
.clk(tx_clk),
.txd(txd),
.tx_en(tx_en),
.tx_er(tx_er)
);
ifg_timer tx_2 (
.crs(crs),
.full_duplex(full_duplex),
.transmit_enable(transmit_enable),
.clk(tx_clk),
.reset_n(reset_n),
.transmit_available_p(transmit_available_p)
);
defer_counter tx_3 (
.transmit_available_p(transmit_available_p),
.transmit_new_p(transmit_new_p),
.clk(tx_clk),
.reset_n(reset_n),
.excess_deferral(excess_deferral)
);
frame_length_counter tx_4 (
.transmit_enable(transmit_enable),
.transmit_fcs(transmit_fcs),
.clk(tx_clk),
.reset_n(reset_n),
.count_length(count_length),
.count_fcs(count_fcs),
.excessive_length(excessive_length),
.transmit_64byte(transmit_64byte)
);
//coll_counter tx_5 (
//.transmit_new_p(transmit_new_p),
//.transmit_enable(transmit_enable),
// .transmit_preamble(transmit_preamble),
// .transmit_sfd(transmit_sfd),
// .transmit_64byte(transmit_64byte),
// .clk(tx_clk),
// .reset_n(reset_n),
// .coll(coll),
// .full_duplex(full_duplex),
// .coll_event_p(coll_event_p),
// .late_coll(late_coll),
// .excessive_coll(excessive_coll),
// .coll_attempt(coll_attempt)
// );
//random_number_gen tx_6 (
// .coll_attempt(coll_attempt),
// .clk(tx_clk),
// .reset_n(reset_n),
// .random(random)
// );
//backoff_timer tx_7 (
//.start_backoff(start_backoff),
//.random(random),
//.clk(tx_clk),
//.reset_n(reset_n),
//.backoff_p(backoff_p)
//);
//jam_timer tx_8 (
//.coll_event_p(coll_event_p),
//.clk(tx_clk),
//.reset_n(reset_n),
//.count_jam(count_jam)
//);
crc_gen tx_9 (
.compute_crc(compute_crc),
.data(data),
.clk(tx_clk),
.reset_n(reset_n),
.crc(crc)
);
data_mux tx_10(
.data_select(data_select),
.data_in(tx_data),
.crc(crc),
.data_out(data)
);
tx_state_machine tx_11 (
.tx_sof(tx_sof),
.tx_eof(tx_eof),
.tx_underrun(tx_underrun),
.clk(tx_clk),
.reset_n(reset_n),
.transmit_available_p(transmit_available_p),
.excess_deferral(excess_deferral),
.coll_event_p(coll_event_p),
.late_coll(late_coll),
.excessive_coll(excessive_coll),
.backoff_p(backoff_p),
.count_length(count_length),
.count_fcs(count_fcs),
.excessive_length(excessive_length),
.count_jam(count_jam),
.tx_data_used(tx_data_used),
.tx_done(tx_done),
.tx_abort(tx_abort),
.tx_retransmit(tx_retransmit),
.tx_status(tx_status),
.tx_status_valid_n(tx_status_valid_n),
.transmit_new_p(transmit_new_p),
.transmit_enable(transmit_enable),
.transmit_preamble(transmit_preamble),
.transmit_sfd(transmit_sfd),
.transmit_fcs(transmit_fcs),
.transmit_error(transmit_error),
.start_backoff(start_backoff),
.compute_crc(compute_crc),
.data_select(data_select)
);
`define CRC_INIT_VALUE (32'hFFFF_FFFF)
`define CRC_IDLE (2'b00)
`define CRC_RUN (2'b01)
`define CRC_STOP (2'b11)
module crc_gen (
compute_crc,
data,
clk,
reset_n,
crc
);
input compute_crc;
input [7:0] data;
input clk;
input reset_n;
output [7:0] crc;
reg [1:0] state_crc;
reg [31:0] crc_buffer;
reg [2:0] crc_end;
function [31:0] count_crc; // the first serial data bit is d [0]
input [3:0] d;
input [31:0] c;
reg [31:0] new_crc;
begin
new_crc[0] = d[3] ^ c[28];
new_crc[1] = d[2] ^ d[3] ^ c[28] ^ c[29];
new_crc[2] = d[1] ^ d[2] ^ d[3] ^ c[28] ^ c[29] ^ c[30];
new_crc[3] = d[0] ^ d[1] ^ d[2] ^ c[29] ^ c[30] ^ c[31];
new_crc[4] = d[0] ^ d[1] ^ d[3] ^ c[0] ^ c[28] ^ c[30] ^ c[31];
new_crc[5] = d[0] ^ d[2] ^ d[3] ^ c[1] ^ c[28] ^ c[29] ^ c[31];
new_crc[6] = d[1] ^ d[2] ^ c[2] ^ c[29] ^ c[30];
new_crc[7] = d[0] ^ d[1] ^ d[3] ^ c[3] ^ c[28] ^ c[30] ^ c[31];
new_crc[8] = d[0] ^ d[2] ^ d[3] ^ c[4] ^ c[28] ^ c[29] ^ c[31];
new_crc[9] = d[1] ^ d[2] ^ c[5] ^ c[29] ^ c[30];
new_crc[10] = d[0] ^ d[1] ^ d[3] ^ c[6] ^ c[28] ^ c[30] ^ c[31];
new_crc[11] = d[0] ^ d[2] ^ d[3] ^ c[7] ^ c[28] ^ c[29] ^ c[31];
new_crc[12] = d[1] ^ d[2] ^ d[3] ^ c[8] ^ c[28] ^ c[29] ^ c[30];
new_crc[13] = d[0] ^ d[1] ^ d[2] ^ c[9] ^ c[29] ^ c[30] ^ c[31];
new_crc[14] = d[0] ^ d[1] ^ c[10] ^ c[30] ^ c[31];
new_crc[15] = d[0] ^ c[11] ^ c[31];
new_crc[16] = d[3] ^ c[12] ^ c[28];
new_crc[17] = d[2] ^ c[13] ^ c[29];
new_crc[18] = d[1] ^ c[14] ^ c[30];
new_crc[19] = d[0] ^ c[15] ^ c[31];
new_crc[20] = c[16];
new_crc[21] = c[17];
new_crc[22] = d[3] ^ c[18] ^ c[28];
new_crc[23] = d[2] ^ d[3] ^ c[19] ^ c[28] ^ c[29];
new_crc[24] = d[1] ^ d[2] ^ c[20] ^ c[29] ^ c[30];
new_crc[25] = d[0] ^ d[1] ^ c[21] ^ c[30] ^ c[31];
new_crc[26] = d[0] ^ d[3] ^ c[22] ^ c[28] ^ c[31];
new_crc[27] = d[2] ^ c[23] ^ c[29];
new_crc[28] = d[1] ^ c[24] ^ c[30];
new_crc[29] = d[0] ^ c[25] ^ c[31];
new_crc[30] = c[26];
new_crc[31] = c[27];
count_crc = new_crc;
end
endfunction
assign crc [7] = ~ crc_buffer [24];
assign crc [6] = ~ crc_buffer [25];
assign crc [5] = ~ crc_buffer [26];
assign crc [4] = ~ crc_buffer [27];
assign crc [3] = ~ crc_buffer [28];
assign crc [2] = ~ crc_buffer [29];
assign crc [1] = ~ crc_buffer [30];
assign crc [0] = ~ crc_buffer [31];
always @(posedge clk or negedge reset_n)
if (!reset_n)
state_crc <= `CRC_IDLE;
else
case (state_crc)
`CRC_IDLE : if (compute_crc)
begin
state_crc <= `CRC_RUN;
crc_buffer <= count_crc (data,`CRC_INIT_VALUE);
end
else
begin
state_crc <= `CRC_IDLE;
crc_buffer <= 32'h0000_0000;
crc_end <= 3'd0;
end
`CRC_RUN : if (!compute_crc)
begin
state_crc <= `CRC_STOP;
crc_buffer <= crc_buffer << 8;
end
else
begin
state_crc <= `CRC_RUN;
crc_buffer <= count_crc (data,crc_buffer);
end
`CRC_STOP : if (crc_end == 3'110)
begin
state_crc <= `CRC_IDLE;
crc_buffer <= 32'h0000_0000;
end
else
begin
state_crc <= `CRC_STOP;
crc_buffer <= crc_buffer << 4;
crc_end <= crc_end + 1'b1;
end
endcase
endmodule
`define PATTERN_PREAMBLE (8'b01010101)
`define PATTERN_SFD (8'b11010101)
module data_mux (
data_select,
data_in,
crc,
data_out,
count_length
);
input [2:0] data_select;
input [7:0] data_in;
input [7:0] crc;
input [7:0] count_length ;
output [7:0] data_out;
reg [7:0] data_out;
always @(data_select or data_in or crc)
case (data_select)
3'b000 : data_out = data_in;
3'b001 : data_out = `PATTERN_PREAMBLE;
3'b010 : data_out = `PATTERN_SFD;
3'b011 : data_out = crc;
3'b100 : data_out = src_add;
3'b101 : data_out = dst_add;
3'b110 : data_out = count_length;
default : data_out = 8'h00;
endcase
endmodule
module fifo_synch (
data,
transmit_enable,
transmit_error,
clk,
txd,
tx_en,
tx_er
);
input [7:0] data;
input transmit_enable;
input transmit_error;
input clk;
output [7:0] txd;
output tx_en;
output tx_er;
reg [7:0] txd;
reg tx_en;
reg tx_er;
always @(posedge clk)
if (transmit_enable)
begin
txd <= data;
tx_en <= 1'b1;
tx_er <= transmit_error;
end
else
begin
txd <= 8'h00;
tx_en <= 1'b0;
tx_er <= 1'b0;
end
endmodule
`define COUNT_LENGTH_IDLE (2'b00)
`define COUNT_LENGTH_RUN (2'b01)
`define COUNT_LENGTH_FCS (2'b11)
`define MIN_LENGTH (12'd144)
`define MAX_LENGTH (12'd3052)
module frame_length_counter (
transmit_enable,
transmit_fcs,
clk,
reset_n,
count_length,
count_fcs,
excessive_length,
transmit_64byte
);
input transmit_enable;
input transmit_fcs;
input clk;
input reset_n;
output [11:0] count_length;
output [3:0] count_fcs;
output excessive_length;
output transmit_64byte;
reg [11:0] count_length;
reg [3:0] count_fcs;
reg excessive_length;
reg transmit_64byte;
reg [1:0] state_length;
function [11:0] inc_length;
input [11:0] count_length;
begin
inc_length = count_length + 1'b1;
end
endfunction
always @(posedge clk or negedge reset_n)
if (!reset_n)
begin
state_length <= `COUNT_LENGTH_IDLE;
count_length <= 12'd0;
count_fcs <= 4'd0;
end
else
case (state_length)
`COUNT_LENGTH_IDLE : if (transmit_enable)
begin
state_length <= `COUNT_LENGTH_RUN;
count_length <= 12'd1;
end
else
state_length <= `COUNT_LENGTH_IDLE;
`COUNT_LENGTH_RUN : if (!transmit_enable)
state_length <= `COUNT_LENGTH_IDLE;
else
if (transmit_fcs)
begin
state_length <= `COUNT_LENGTH_FCS;
count_length <= inc_length(count_length);
count_fcs <= 4'd1;
end
else
begin
state_length <= `COUNT_LENGTH_RUN;
count_length <= inc_length(count_length);
end
`COUNT_LENGTH_FCS : if (!transmit_enable)
state_length <= `COUNT_LENGTH_IDLE;
else
begin
state_length <= `COUNT_LENGTH_FCS;
count_length <= inc_length(count_length);
count_fcs <= (count_fcs + 1'b1);
end
endcase
always @(count_length)
begin
transmit_64byte = (count_length > `MIN_LENGTH-1) ? 1'b1 : 1'b0;
excessive_length = (count_length > `MAX_LENGTH-1) ? 1'b1 : 1'b0;
end
endmodule
`define IFG_LENGTH_1 (5'd15)
`define IFG_LENGTH_2 (5'd22)
`define IFG_IDLE (1'b0)
`define IFG_RUN (1'b1)
module ifg_timer (
crs,
full_duplex,
transmit_enable,
clk,
reset_n,
transmit_available_p
);
input crs;
input full_duplex;
input transmit_enable;
input clk;
input reset_n;
output transmit_available_p;
reg transmit_available_p;
reg [4:0] count_ifg;
reg state_ifg;
function [4:0] inc_ifg;
input [4:0] count_ifg;
begin
inc_ifg = count_ifg + 1'b1;
end
endfunction
always @(posedge clk or negedge reset_n)
if (!reset_n)
state_ifg <= `IFG_IDLE;
else
if (full_duplex)
case (state_ifg)
`IFG_IDLE : if (!transmit_enable)
begin
state_ifg <= `IFG_RUN;
count_ifg <= 5'd1;
transmit_available_p <= 1'b0;
end
else
begin
state_ifg <= `IFG_IDLE;
count_ifg <= 5'd0;
transmit_available_p <= 1'b0;
end
`IFG_RUN : if (transmit_enable)
state_ifg <= `IFG_IDLE;
else
if (count_ifg == `IFG_LENGTH_2-1)
begin
state_ifg <= `IFG_IDLE;
transmit_available_p <= 1'b1;
end
else
begin
state_ifg <= `IFG_RUN;
count_ifg <= inc_ifg(count_ifg);
end
endcase
else
case (state_ifg)
`IFG_IDLE : if (!crs)
begin
state_ifg <= `IFG_RUN;
count_ifg <= 5'd1;
transmit_available_p <= 1'b0;
end
else
begin
state_ifg <= `IFG_IDLE;
count_ifg <= 5'd0;
transmit_available_p <= 1'b0;
end
`IFG_RUN : if (crs && (count_ifg <= `IFG_LENGTH_1-1))
state_ifg <= `IFG_IDLE;
else
if (count_ifg == `IFG_LENGTH_2-1)
begin
state_ifg <= `IFG_IDLE;
transmit_available_p <= 1'b1;
end
else
begin
state_ifg <= `IFG_RUN;
count_ifg <= inc_ifg(count_ifg);
end
endcase
endmodule
`define TRANSMIT_IDLE (4'b0000)
`define NEW_TRANSMIT (4'b0001)
`define WAIT_TRANSMIT (4'b0011)
`define TRANSMIT_PREAMBLE (4'b0010)
`define TRANSMIT_SFD (4'b0110)
`define TRANSMIT_DATA (4'b0111)
`define TRANSMIT_PAD (4'b0101)
`define TRANSMIT_FCS (4'b0100)
`define WAIT_DONE (4'b1100)
`define TRANSMIT_DONE (4'b1101)
`define TRANSMIT_JAM (4'b1111)
`define WAIT_BACKOFF (4'b1110)
`define WAIT_ABORT (4'b1010)
`define TRANSMIT_ABORT (4'b1011)
`define WRITE_STATUS (4'b1001)
//`define (4'b1000)
`define PREAMBLE_LENGTH (12'd15)
`define SFD_LENGTH (12'd1)
`define DATA_LENGTH (12'd120)
`define FCS_LENGTH (4'd8)
`define JAM_LENGTH (4'd8)
`define WIDTH_STATUS 7
module tx_state_machine (
tx_sof,
tx_eof,
tx_underrun,
clk,
reset_n,
transmit_available_p,
excess_deferral,
coll_event_p,
late_coll,
excessive_coll,
backoff_p,
count_length,
count_fcs,
excessive_length,
count_jam,
tx_data_used,
tx_done,
tx_abort,
tx_retransmit,
tx_status,
tx_status_valid_n,
transmit_new_p,
transmit_enable,
transmit_preamble,
transmit_sfd,
transmit_fcs,
transmit_error,
start_backoff,
compute_crc,
data_select
);
input tx_sof;
input tx_eof;
input tx_underrun;
input clk;
input reset_n;
input transmit_available_p;
input excess_deferral;
input excessive_length;
input excessive_coll;
input late_coll;
input coll_event_p;
input backoff_p;
input [11:0] count_length;
input [3:0] count_fcs;
input [3:0] count_jam;
output tx_data_used;
output tx_done;
output tx_abort;
output tx_retransmit;
output [`WIDTH_STATUS-1:0] tx_status;
output tx_status_valid_n;
output transmit_new_p;
output transmit_enable;
output transmit_preamble;
output transmit_sfd;
output transmit_fcs;
output transmit_error;
output start_backoff;
output compute_crc;
output [2:0] data_select;
reg tx_data_used;
reg tx_done;
reg tx_abort;
reg tx_retransmit;
// reg [`WIDTH_STATUS-1:0] tx_status;
reg tx_status_valid_n;
reg transmit_new_p;
reg transmit_enable;
reg transmit_preamble;
reg transmit_sfd;
reg transmit_fcs;
reg transmit_error;
reg start_backoff;
reg compute_crc;
reg [2:0] data_select;
reg [3:0] current_tx_state;
reg [3:0] next_tx_state;
always @(posedge clk or negedge reset_n)
if (!reset_n)
current_tx_state <= `TRANSMIT_IDLE;
else
current_tx_state <= next_tx_state;
always @(current_tx_state or tx_sof or tx_eof or tx_underrun or
transmit_available_p or excess_deferral or excessive_length or
excessive_coll or late_coll or coll_event_p or backoff_p or
count_length or count_fcs or count_jam)
case (current_tx_state)
`TRANSMIT_IDLE : if (tx_sof)
next_tx_state = `NEW_TRANSMIT;
else
next_tx_state = `TRANSMIT_IDLE;
`NEW_TRANSMIT : if (!tx_sof)
next_tx_state = `TRANSMIT_IDLE;
else
next_tx_state = `WAIT_TRANSMIT;
`WAIT_TRANSMIT : if (!tx_sof)
next_tx_state = `TRANSMIT_IDLE;
else
if (excess_deferral)
next_tx_state = `WAIT_ABORT;
else
if (transmit_available_p)
next_tx_state = `TRANSMIT_PREAMBLE;
else
next_tx_state = `WAIT_TRANSMIT;
`TRANSMIT_PREAMBLE : if (!tx_sof)
next_tx_state = `TRANSMIT_IDLE;
else
if (count_length == `PREAMBLE_LENGTH-1)
next_tx_state = `TRANSMIT_SFD;
else
next_tx_state = `TRANSMIT_PREAMBLE;
`TRANSMIT_SFD : if (!tx_sof)
next_tx_state = `TRANSMIT_IDLE;
else
next_tx_state = `TRANSMIT_DATA;
`TRANSMIT_DATA : if (coll_event_p)
next_tx_state = `TRANSMIT_JAM;
else
if (tx_underrun || excessive_length)
next_tx_state = `WAIT_ABORT;
else
if (tx_eof)
begin
if (count_length < (`PREAMBLE_LENGTH+`SFD_LENGTH+`DATA_LENGTH-1))
next_tx_state = `TRANSMIT_PAD;
else
next_tx_state = `TRANSMIT_FCS;
end
else
next_tx_state = `TRANSMIT_DATA;
`TRANSMIT_PAD : if (coll_event_p)
next_tx_state = `TRANSMIT_JAM;
else
if (count_length == (`PREAMBLE_LENGTH+`SFD_LENGTH+`DATA_LENGTH-1))
next_tx_state = `TRANSMIT_FCS;
else
next_tx_state = `TRANSMIT_PAD;
`TRANSMIT_FCS : if (coll_event_p)
next_tx_state = `TRANSMIT_JAM;
else
if (excessive_length)
next_tx_state = `WAIT_ABORT;
else
if (count_fcs == `FCS_LENGTH-1)
next_tx_state = `WAIT_DONE;
else
next_tx_state = `TRANSMIT_FCS;
`TRANSMIT_JAM : if (count_jam == `JAM_LENGTH-3)
begin
if (late_coll || excessive_coll)
next_tx_state = `WAIT_ABORT;
else
next_tx_state = `WAIT_BACKOFF;
end
else
next_tx_state = `TRANSMIT_JAM;
`WAIT_BACKOFF : if (backoff_p)
next_tx_state = `WAIT_TRANSMIT;
else
next_tx_state = `WAIT_BACKOFF;
`WAIT_DONE : if (coll_event_p)
next_tx_state = `TRANSMIT_JAM;
else
if (excessive_length)
next_tx_state = `WAIT_ABORT;
else
next_tx_state = `TRANSMIT_DONE;
`TRANSMIT_DONE : next_tx_state = `WRITE_STATUS;
`WAIT_ABORT : next_tx_state = `TRANSMIT_ABORT;
`TRANSMIT_ABORT : next_tx_state = `WRITE_STATUS;
`WRITE_STATUS : next_tx_state = `TRANSMIT_IDLE;
default : next_tx_state = `TRANSMIT_IDLE;
endcase
always @(current_tx_state)
case (current_tx_state)
`TRANSMIT_IDLE :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`NEW_TRANSMIT :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b1;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`WAIT_TRANSMIT :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_PREAMBLE :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b1;
transmit_preamble = 1'b1;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b001;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_SFD :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b1;
transmit_preamble = 1'b0;
transmit_sfd = 1'b1;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b010;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_DATA :
begin
tx_data_used = 1'b1;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b1;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b1;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_PAD :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b1;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b001;
compute_crc = 1'b1;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_FCS :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b1;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b1;
start_backoff = 1'b0;
data_select = 3'b011;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`WAIT_DONE :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_DONE :
begin
tx_data_used = 1'b0;
tx_done = 1'b1;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_JAM :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b1;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b001;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`WAIT_BACKOFF :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b1;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b1;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`WAIT_ABORT :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`TRANSMIT_ABORT :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b1;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
`WRITE_STATUS :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b0;
end
default :
begin
tx_data_used = 1'b0;
tx_done = 1'b0;
tx_abort = 1'b0;
tx_retransmit = 1'b0;
transmit_new_p = 1'b0;
transmit_enable = 1'b0;
transmit_preamble = 1'b0;
transmit_sfd = 1'b0;
transmit_fcs = 1'b0;
start_backoff = 1'b0;
data_select = 3'b000;
compute_crc = 1'b0;
tx_status_valid_n = 1'b1;
end
endcase
assign tx_status [0] = excess_deferral;
assign tx_status [1] = late_coll;
assign tx_status [2] = excessive_coll;
assign tx_status [3] = 1'b0;
assign tx_status [4] = excessive_length;
assign tx_status [5] = (excess_deferral | late_coll | excessive_coll |
tx_underrun | excessive_length);
assign tx_status [6] = ~(excess_deferral | late_coll | excessive_coll |
tx_underrun | excessive_length);
always @(posedge clk)
if (tx_underrun)
transmit_error <= 1'b1;
else
transmit_error <= 1'b0;
endmodule