Add basic acking to synacking
This commit is contained in:
@@ -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}")
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user