module tx_prot_engine (input clk, input rst, // To MAC input Tx_mac_wa, output Tx_mac_wr, output [31:0] Tx_mac_data, output [1:0] Tx_mac_BE, output Tx_mac_sop, output Tx_mac_eop, // To buffer interface input [31:0] rd_dat_i, output rd_read_o, output rd_done_o, output rd_error_o, input rd_sop_i, input rd_eop_i, // To control input set_stb, input [7:0] set_addr, input [31:0] set_data, // Protocol Stuff input [15:0] rx_fifo_status, input [7:0] rx_seqnum //input [7:0] tx_channel, //input [7:0] tx_flags ); wire [3:0] hdr_adr; wire [31:0] hdr_dat; wire [7:0] tx_channel; header_ram #(.REGNUM(32),.WIDTH(32)) tx_header_ram (.clk(clk),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), .addr(hdr_adr),.q(hdr_dat)); setting_reg #(.my_addr(32)) sr_channel (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),.in(set_data), .out(tx_channel),.changed()); // Might as well use a shortfifo here since they are basically free wire empty, full, sfifo_write, sfifo_read; wire [33:0] sfifo_in, sfifo_out; shortfifo #(.WIDTH(34)) txmac_sfifo (.clk(clk),.rst(rst),.clear(0), .datain(sfifo_in),.write(sfifo_write),.full(full), .dataout(sfifo_out),.read(sfifo_read),.empty(empty)); // MAC side signals // Inputs -- Tx_mac_wa, sfifo_out, empty // outputs -- sfifo_read, Tx_mac_data, Tx_mac_wr, Tx_mac_BE, Tx_mac_sop, Tx_mac_eop // We are allowed to do one more write after we are told the FIFO is full // This allows us to register the _wa signal and speed up timing. reg tx_mac_wa_d1; always @(posedge clk) tx_mac_wa_d1 <= Tx_mac_wa; reg [2:0] prot_state; localparam PROT_IDLE = 0; localparam PROT_HDR1 = 1; localparam PROT_HDR2 = 2; localparam PROT_HDR3 = 3; localparam PROT_HDR4 = 4; localparam PROT_HDR5 = 5; localparam PROT_PKT = 6; reg [7:0] tx_seqnum; reg all_match; always @(posedge clk) if(rst) tx_seqnum <= 0; else if(set_stb & (set_addr == 36)) tx_seqnum <= set_data[7:0]; else if(tx_mac_wa_d1 & all_match & (prot_state == PROT_HDR5)) tx_seqnum <= tx_seqnum + 1; always @(posedge clk) if(rst) prot_state <= PROT_IDLE; else if(tx_mac_wa_d1 & ~empty) case(prot_state) PROT_IDLE : prot_state <= PROT_HDR1; PROT_HDR1 : prot_state <= PROT_HDR2; PROT_HDR2 : prot_state <= PROT_HDR3; PROT_HDR3 : prot_state <= PROT_HDR4; PROT_HDR4 : prot_state <= PROT_HDR5; PROT_HDR5 : prot_state <= PROT_PKT; PROT_PKT : if(sfifo_out[32] & ~empty) prot_state <= PROT_IDLE; default : prot_state <= PROT_IDLE; endcase // case(prot_state) assign hdr_adr = {1'b0,prot_state}; wire match = (hdr_dat == sfifo_out[31:0]); always @(posedge clk) if(prot_state == PROT_IDLE) all_match <= 1; else if(tx_mac_wa_d1 & ~empty & ((prot_state==PROT_HDR1)|(prot_state==PROT_HDR2)|(prot_state==PROT_HDR3))) all_match <= all_match & match; localparam ETH_TYPE = 16'hBEEF; assign Tx_mac_data = ((prot_state == PROT_HDR5) & all_match) ? {rx_fifo_status,tx_seqnum,rx_seqnum} : sfifo_out[31:0]; assign sfifo_read = (prot_state != PROT_IDLE) & ~empty & tx_mac_wa_d1; assign Tx_mac_wr = sfifo_read; assign Tx_mac_BE = 0; // Since we only deal with packets that are multiples of 32 bits long assign Tx_mac_sop = sfifo_out[33]; assign Tx_mac_eop = sfifo_out[32]; // BUFFER side signals reg xfer_active; always @(posedge clk) if(rst) xfer_active <= 0; else if(rd_eop_i & ~full) xfer_active <= 0; else if(rd_sop_i) xfer_active <= 1; assign sfifo_in = {rd_sop_i, rd_eop_i, rd_dat_i}; assign sfifo_write = xfer_active & ~full; assign rd_read_o = sfifo_write; assign rd_done_o = 0; // Always send everything we're given? assign rd_error_o = 0; // No possible error situations? endmodule // tx_prot_engine