Add basic acking to synacking

This commit is contained in:
Byron Lathi
2024-09-08 18:15:43 -07:00
parent 945889e542
commit e1f94f455c
9 changed files with 227 additions and 12 deletions

View File

@@ -138,4 +138,22 @@ async def test_simple(dut):
await tb.mii_phy.rx.send(GmiiFrame.from_payload(tcp_synack))
await Timer(Decimal(CLK_PERIOD_NS * 800), units='ns')
resp = await tb.mii_phy.tx.recv() # type: GmiiFrame
packet = Ether(resp.get_payload())
tb.log.info(f"Packet Type: {packet.type:x}")
ip_packet = packet.payload
assert isinstance(ip_packet, IP)
tcp_packet = ip_packet.payload
assert isinstance(tcp_packet, TCP)
tb.log.info(f"Source Port: {tcp_packet.sport}")
tb.log.info(f"Dest Port: {tcp_packet.dport}")
tb.log.info(f"Seq: {tcp_packet.seq}")
tb.log.info(f"Ack: {tcp_packet.ack}")
tb.log.info(f"Data Offs: {tcp_packet.dataofs}")
tb.log.info(f"flags: {tcp_packet.flags}")
tb.log.info(f"window: {tcp_packet.window}")
tb.log.info(f"Checksum: {tcp_packet.chksum}")

View File

@@ -9,6 +9,7 @@ src/regs/ntw_top_regfile.sv
src/network_processor.sv
src/tcp_pkg.sv
src/tcp_tx_ctrl.sv
src/tcp_rx_ctrl.sv
src/tcp_packet_generator.sv
src/tcp_state_manager.sv
src/tcp_stream.sv

View File

@@ -37,11 +37,15 @@ end
always_comb begin
m_ip.ip_hdr_valid = '0;
m_ip.ip_payload_axis_tvalid = '0;
m_ip.ip_payload_axis_tlast = '0;
o_packet_done = '0;
case (state)
IDLE: begin
counter_next = '0;
if (i_hdr_valid) begin
m_ip.ip_hdr_valid = '1;
m_ip.ip_dscp = '0;

View File

@@ -2,10 +2,114 @@ module tcp_parser(
input wire i_clk,
input wire i_rst,
ip_intf.SLAVE s_ip
ip_intf.SLAVE s_ip,
axis_intf.MASTER m_axis,
output wire [31:0] o_seq_number,
output wire [31:0] o_ack_number,
output wire [7:0] o_flags,
output wire [15:0] o_window_size,
output wire o_hdr_valid
);
assign s_ip.ip_hdr_ready = '1;
assign s_ip.ip_payload_axis_tready = '1;
enum logic {HEADER, PAYLOAD} state, state_next;
logic [4:0] counter, counter_next;
logic hdr_valid;
logic [31:0] sequence_num, sequence_num_next;
logic [31:0] ack_num, ack_num_next;
logic [3:0] data_offs, data_offs_next;
logic [7:0] flags, flags_next;
logic [15:0] window_size, window_size_next;
logic [15:0] checksum, checksum_next;
assign o_seq_number = sequence_num;
assign o_ack_number = ack_num;
assign o_flags = flags;
assign o_window_size = window_size;
assign o_hdr_valid = hdr_valid;
always_ff @(posedge i_clk) begin
if (i_rst) begin
state <= HEADER;
counter <= '0;
sequence_num <= '0;
ack_num <= '0;
data_offs <= '0;
flags <= '0;
window_size <= '0;
checksum <= '0;
end else begin
state <= state_next;
counter <= counter_next;
sequence_num <= sequence_num_next;
ack_num <= ack_num_next;
data_offs <= data_offs_next;
flags <= flags_next;
window_size <= window_size_next;
checksum <= checksum_next;
end
end
always_comb begin
sequence_num_next = sequence_num;
ack_num_next = ack_num;
data_offs_next = data_offs;
flags_next = flags;
window_size_next = window_size;
checksum_next = checksum;
hdr_valid = '0;
case (state)
HEADER: begin
s_ip.ip_hdr_ready = '1;
s_ip.ip_payload_axis_tready = '1;
if (s_ip.ip_payload_axis_tvalid) begin
counter_next = counter + 1;
case (counter)
4: sequence_num_next = {s_ip.ip_payload_axis_tdata, sequence_num[23:0]};
5: sequence_num_next = {sequence_num[31:24], s_ip.ip_payload_axis_tdata, sequence_num[15:0]};
6: sequence_num_next = {sequence_num[31:16], s_ip.ip_payload_axis_tdata, sequence_num[7:0]};
7: sequence_num_next = {sequence_num[31:8], s_ip.ip_payload_axis_tdata};
4: ack_num_next = {s_ip.ip_payload_axis_tdata, ack_num[23:0]};
5: ack_num_next = {ack_num[31:24], s_ip.ip_payload_axis_tdata, ack_num[15:0]};
6: ack_num_next = {ack_num[31:16], s_ip.ip_payload_axis_tdata, ack_num[8:0]};
7: ack_num_next = {ack_num[31:8], s_ip.ip_payload_axis_tdata};
12: data_offs_next = s_ip.ip_payload_axis_tdata[7:4];
13: flags_next = s_ip.ip_payload_axis_tdata;
14: window_size_next = {s_ip.ip_payload_axis_tdata, window_size[7:0]};
15: window_size_next = {window_size[15:8], s_ip.ip_payload_axis_tdata};
16: checksum_next = {s_ip.ip_payload_axis_tdata, checksum[7:0]};
17: checksum_next = {checksum[15:8], s_ip.ip_payload_axis_tdata};
19: begin
state_next = PAYLOAD;
hdr_valid = '1;
end
endcase
if (s_ip.ip_payload_axis_tlast) begin
counter_next = '0;
state_next = HEADER; // if we see last then we are done, its possible to have no data
end
end
end
PAYLOAD: begin
if (s_ip.ip_payload_axis_tlast) begin
counter_next = '0;
state_next = HEADER;
end
end
endcase
end
endmodule

View File

@@ -0,0 +1,27 @@
module tcp_rx_ctrl (
input wire i_clk,
input wire i_rst,
output tcp_pkg::rx_msg_t o_rx_msg,
output logic o_rx_msg_valid,
input logic i_rx_msg_ack,
input wire [31:0] i_seq_number,
input wire [31:0] i_ack_number,
input wire [15:0] i_source_port,
input wire [15:0] i_dest_port,
input wire [7:0] i_flags,
input wire [15:0] i_window_size,
input wire i_hdr_valid
);
always_ff @(posedge i_clk) begin
if (i_hdr_valid) begin
if (i_flags & 8'h12) begin
o_rx_msg = RX_MSG_RECV_SYNACK;
o_rx_msg_valid = '1;
end
end
end
endmodule

View File

@@ -23,7 +23,8 @@ module tcp_state_manager(
enum logic [3:0] {
IDLE,
SYN_RCVD, // In this design, this state should not be reached!
SYN_SENT,
SYN_SENT_1,
SYN_SENT_2,
ESTABLISHED,
WAIT_CLOSE,
LAST_ACK,
@@ -62,13 +63,28 @@ always_comb begin
o_tx_ctrl_valid = '1;
if (i_tx_ctrl_ack) begin
tcp_state_next = SYN_SENT;
tcp_state_next = SYN_SENT_1;
end
end
end
SYN_SENT: begin
// $display("SYN_SENT not implemented");
SYN_SENT_1: begin
if (i_rx_msg_valid && i_rx_msg== RX_MSG_RECV_SYNACK) begin
tcp_state_next = SYN_SENT_2;
end
end
SYN_SENT_2: begin
o_tx_ctrl = TX_CTRL_SEND_ACK;
o_tx_ctrl_valid = '1;
if (i_tx_ctrl_ack) begin
tcp_state_next = ESTABLISHED;
end
end
ESTABLISHED: begin
end
endcase
end

View File

@@ -33,6 +33,7 @@ axis_intf m2s_axis();
axis_intf s2m_axis();
axis_intf m2s_post_saf_axis();
axis_intf s2m_pre_saf_axis();
// regs
tcp_stream_regs_pkg::tcp_stream_regs__in_t hwif_in;
@@ -42,6 +43,10 @@ tcp_pkg::tx_ctrl_t tx_ctrl;
logic tx_ctrl_valid;
logic tx_ctrl_ack;
tcp_pkg::rx_msg_t rx_msg;
logic rx_msg_valid;
logic rx_msg_ack;
logic [31:0] w_tx_seq_number;
logic [31:0] w_tx_ack_number;
logic [7:0] w_tx_flags;
@@ -49,7 +54,12 @@ logic [15:0] w_tx_window_size;
logic w_tx_hdr_valid;
logic w_tx_packet_done;
tcp_pkg::rx_msg_t rx_msg;
logic [31:0] w_rx_seq_number;
logic [31:0] w_rx_ack_number;
logic [7:0] w_rx_flags;
logic [15:0] w_rx_window_size;
logic w_rx_hdr_valid;
assign o_tcp_port = hwif_out.source_port.d.value;
@@ -113,7 +123,11 @@ tcp_state_manager u_tcp_state_manager (
.o_tx_ctrl (tx_ctrl),
.o_tx_ctrl_valid (tx_ctrl_valid),
.i_tx_ctrl_ack (tx_ctrl_ack)
.i_tx_ctrl_ack (tx_ctrl_ack),
.i_rx_msg (rx_msg),
.i_rx_msg_valid (rx_msg_valid),
.o_rx_msg_ack (rx_msg_ack)
);
@@ -199,10 +213,31 @@ tcp_parser u_tcp_parser (
.i_clk (clk),
.i_rst (rst),
.s_ip (s_ip_rx)
.s_ip (s_ip_rx),
.m_axis (s2m_pre_saf_axis),
.o_seq_number (w_rx_seq_number),
.o_ack_number (w_rx_ack_number),
.o_flags (w_rx_flags),
.o_window_size (w_rx_window_size),
.o_hdr_valid (w_rx_hdr_valid)
);
// rx control
tcp_rx_ctrl u_tcp_rx_ctrl (
.i_clk (clk),
.i_rst (rst),
.o_rx_msg (rx_msg),
.o_rx_msg_valid (rx_msg_valid),
.i_rx_msg_ack (rx_msg_ack),
.i_seq_number (w_rx_seq_number),
.i_ack_number (w_rx_ack_number),
.i_flags (w_rx_flags),
.i_window_size (w_rx_window_size),
.i_hdr_valid (w_rx_hdr_valid)
);
// rx buffer

View File

@@ -26,7 +26,7 @@ localparam FLAG_URG = (1 << 5);
localparam FLAG_ECE = (1 << 6);
localparam FLAG_CWR = (1 << 7);
enum logic [2:0] {IDLE, SEND_SYN} state, state_next;
enum logic [2:0] {IDLE, SEND_SYN, SEND_ACK} state, state_next;
always_ff @(posedge i_clk) begin
if (i_rst) begin
@@ -50,6 +50,7 @@ always_comb begin
case (i_tx_ctrl)
TX_CTRL_SEND_SYN: state_next = SEND_SYN;
TX_CTRL_SEND_ACK: state_next = SEND_ACK;
endcase
end
end
@@ -62,6 +63,15 @@ always_comb begin
state_next = IDLE;
end
end
SEND_ACK: begin
o_flags = FLAG_ACK;
o_hdr_valid = '1;
if (i_packet_done) begin
state_next = IDLE;
end
end
endcase
end