blob: 069ebd3d31b8907e69b7871c223ab32c1cf7086c [file] [log] [blame]
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 04.08.2021 17:21:28
// Design Name:
// Module Name: udp_host
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module udp_host(
input wire clk,
input wire rst,
/*
* Ethernet: 100BASE-T MII
*/
input wire [3:0] phy_txd,
input wire phy_tx_en,
output wire phy_tx_clk,
output wire phy_rx_clk,
output wire [3:0] phy_rxd,
output wire phy_rx_dv,
output wire phy_rx_er
);
localparam RX_STATE_IDLE = 2'b00;
localparam RX_STATE_SEND_UDP_FRAME = 2'b01;
localparam RX_STATE_SEND_ARP_RESPONSE = 2'b10;
localparam RX_STATE_ARP_RESPONSE_DONE = 2'b11;
localparam TX_STATE_IDLE = 2'b00;
localparam TX_STATE_RECV_ARP_REQUEST = 2'b01;
localparam TX_STATE_RECV_UDP_FRAME = 2'b10;
localparam TX_STATE_ARP_REQUEST_DONE = 2'b11;
reg [3:0] phy_rxd_reg = 0;
reg phy_rx_dv_reg = 0, phy_rx_er_reg = 0;
reg [3:0] phy_txd_reg = 0;
reg phy_tx_en_reg = 0;
assign phy_tx_clk = ~clk;
assign phy_rx_clk = ~clk;
assign phy_rxd = phy_rxd_reg;
assign phy_rx_dv = phy_rx_dv_reg;
assign phy_rx_er = phy_rx_er_reg;
reg [7:0] rx_udp_frame [0:309];
reg [7:0] rx_arp_frame [0:71];
reg [7:0] tx_udp_frame [0:309];
reg [7:0] tx_arp_frame [0:71];
reg [7:0] tx_udp_frame_diff [0:309];
reg [7:0] tx_arp_frame_diff [0:71];
reg reset_flag = 0;
reg reset_diff = 0;
reg [1:0] rx_state = RX_STATE_IDLE;
reg [1:0] tx_state = TX_STATE_IDLE;
reg [9:0] rx_mem_sp = 0;
reg [9:0] tx_mem_sp = 0;
integer i;
reg first_frame = 1;
initial begin
$readmemb("udp_frame.mem", rx_udp_frame);
$readmemb("arp_resp_frame.mem", rx_arp_frame);
$readmemb("phy_frame.mem", tx_udp_frame_diff);
$readmemb("arp_rqst_frame.mem", tx_arp_frame_diff);
end
always @(negedge rst) reset_flag = ~reset_flag;
always @(posedge clk) begin
phy_txd_reg <= phy_txd;
phy_tx_en_reg <= phy_tx_en;
if(reset_flag^reset_diff) rx_state <= RX_STATE_SEND_UDP_FRAME;
else begin
if(phy_tx_en && tx_state == TX_STATE_IDLE) tx_state <= first_frame ? TX_STATE_RECV_ARP_REQUEST : TX_STATE_RECV_UDP_FRAME;
if(phy_tx_en && tx_state == TX_STATE_ARP_REQUEST_DONE) tx_state <= TX_STATE_RECV_UDP_FRAME;
if(rx_state == RX_STATE_SEND_UDP_FRAME) begin
if(rx_mem_sp == 0) begin
phy_rx_dv_reg <= 1;
phy_rxd_reg <= rx_mem_sp[0] ? rx_udp_frame[rx_mem_sp[9:1]][7:4] : rx_udp_frame[rx_mem_sp[9:1]][3:0];
rx_mem_sp <= rx_mem_sp + 1;
end
else if (rx_mem_sp[9:1] < 310) begin
phy_rxd_reg <= rx_mem_sp[0] ? rx_udp_frame[rx_mem_sp[9:1]][7:4] : rx_udp_frame[rx_mem_sp[9:1]][3:0];
rx_mem_sp = rx_mem_sp + 1;
end
else begin
rx_state <= RX_STATE_IDLE;
rx_mem_sp <= 0;
phy_rxd_reg <= 0;
phy_rx_dv_reg <= 0;
end
end
else if (rx_state == RX_STATE_SEND_ARP_RESPONSE) begin
if(rx_mem_sp == 0) begin
phy_rx_dv_reg <= 1;
phy_rxd_reg <= rx_mem_sp[0] ? rx_arp_frame[rx_mem_sp[9:1]][7:4] : rx_arp_frame[rx_mem_sp[9:1]][3:0];
rx_mem_sp <= rx_mem_sp + 1;
end
else if (rx_mem_sp[9:1] < 72) begin
phy_rxd_reg <= rx_mem_sp[0] ? rx_arp_frame[rx_mem_sp[9:1]][7:4] : rx_arp_frame[rx_mem_sp[9:1]][3:0];
rx_mem_sp = rx_mem_sp + 1;
end
else begin
rx_state <= RX_STATE_ARP_RESPONSE_DONE;
rx_mem_sp <= 0;
phy_rxd_reg <= 0;
phy_rx_dv_reg <= 0;
end
end
else if (rx_state == RX_STATE_ARP_RESPONSE_DONE) begin
end
if (tx_state == TX_STATE_RECV_ARP_REQUEST) begin
if (phy_tx_en_reg) begin
tx_arp_frame[tx_mem_sp[9:1]] <= tx_mem_sp[0] ? {phy_txd_reg, tx_arp_frame[tx_mem_sp[9:1]][3:0]} : {4'b0, phy_txd_reg};
tx_mem_sp <= tx_mem_sp + 1;
end
else if (tx_mem_sp[9:1] == 72 && ~phy_tx_en_reg) begin
for (i = 0; i < 72; i = i + 1) begin
if(tx_arp_frame[i] != tx_arp_frame_diff[i]) begin
$display("ARP request wasn't received properly");
$finish;
end
end
$display("Received ARP request");
tx_state <= TX_STATE_ARP_REQUEST_DONE;
tx_mem_sp <= 0;
end
else begin
$display("ARP request wasn't received properly");
$finish;
end
end
else if (tx_state == TX_STATE_RECV_UDP_FRAME) begin
if (phy_tx_en_reg) begin
tx_udp_frame[tx_mem_sp[9:1]] <= tx_mem_sp[0] ? {phy_txd_reg, tx_udp_frame[tx_mem_sp[9:1]][3:0]} : {4'b0, phy_txd_reg};
tx_mem_sp <= tx_mem_sp + 1;
end
else if (tx_mem_sp[9:1] == 310 && ~phy_tx_en_reg) begin
for (i = 0; i < 310; i = i + 1) begin
if(tx_udp_frame[i] != tx_udp_frame_diff[i]) begin
$display("UDP frame wasn't received properly");
$finish;
end
end
$display("Received UDP frame");
tx_state <= TX_STATE_IDLE;
tx_mem_sp <= 0;
first_frame <= 0;
rx_state <= RX_STATE_SEND_UDP_FRAME;
rx_mem_sp <= 0;
$finish;
end
else begin
$display("UDP frame wasn't received properly");
$finish;
end
end
else if (tx_state == TX_STATE_ARP_REQUEST_DONE && rx_state == RX_STATE_IDLE) rx_state <= RX_STATE_SEND_ARP_RESPONSE;
end
end
endmodule