Commit c15f2eab authored by Antoine Kaufmann's avatar Antoine Kaufmann
Browse files

sims/net/menshen: add

parent 3be11ceb
`timescale 1ns / 1ps
module crossbar #(
parameter STAGE_ID = 0,
parameter PHV_LEN = 48*8+32*8+16*8+256,
parameter ACT_LEN = 25,
parameter width_2B = 16,
parameter width_4B = 32,
parameter width_6B = 48
)
(
input clk,
input rst_n,
//input from PHV
input [PHV_LEN-1:0] phv_in,
input phv_in_valid,
//input from action
input [ACT_LEN*25-1:0] action_in,
input action_in_valid,
output reg ready_out,
//output to the ALU
output reg alu_in_valid,
output reg [width_6B*8-1:0] alu_in_6B_1,
output reg [width_6B*8-1:0] alu_in_6B_2,
output reg [width_4B*8-1:0] alu_in_4B_1,
output reg [width_4B*8-1:0] alu_in_4B_2,
output reg [width_4B*8-1:0] alu_in_4B_3,
output reg [width_2B*8-1:0] alu_in_2B_1,
output reg [width_2B*8-1:0] alu_in_2B_2,
output reg [255:0] phv_remain_data,
//I have to delay action_in for ALUs for 1 cycle
output reg [ACT_LEN*25-1:0] action_out,
output reg action_valid_out,
input ready_in
);
/********intermediate variables declared here********/
integer i;
wire [width_6B-1:0] cont_6B [0:7];
wire [width_4B-1:0] cont_4B [0:7];
wire [width_2B-1:0] cont_2B [0:7];
wire [ACT_LEN-1:0] sub_action [24:0];
/********intermediate variables declared here********/
assign cont_6B[7] = phv_in[PHV_LEN-1 -: width_6B];
assign cont_6B[6] = phv_in[PHV_LEN-1- width_6B -: width_6B];
assign cont_6B[5] = phv_in[PHV_LEN-1-2*width_6B -: width_6B];
assign cont_6B[4] = phv_in[PHV_LEN-1-3*width_6B -: width_6B];
assign cont_6B[3] = phv_in[PHV_LEN-1-4*width_6B -: width_6B];
assign cont_6B[2] = phv_in[PHV_LEN-1-5*width_6B -: width_6B];
assign cont_6B[1] = phv_in[PHV_LEN-1-6*width_6B -: width_6B];
assign cont_6B[0] = phv_in[PHV_LEN-1-7*width_6B -: width_6B];
assign cont_4B[7] = phv_in[PHV_LEN-1-8*width_6B -: width_4B];
assign cont_4B[6] = phv_in[PHV_LEN-1-8*width_6B- width_4B -: width_4B];
assign cont_4B[5] = phv_in[PHV_LEN-1-8*width_6B-2*width_4B -: width_4B];
assign cont_4B[4] = phv_in[PHV_LEN-1-8*width_6B-3*width_4B -: width_4B];
assign cont_4B[3] = phv_in[PHV_LEN-1-8*width_6B-4*width_4B -: width_4B];
assign cont_4B[2] = phv_in[PHV_LEN-1-8*width_6B-5*width_4B -: width_4B];
assign cont_4B[1] = phv_in[PHV_LEN-1-8*width_6B-6*width_4B -: width_4B];
assign cont_4B[0] = phv_in[PHV_LEN-1-8*width_6B-7*width_4B -: width_4B];
assign cont_2B[7] = phv_in[PHV_LEN-1-8*width_6B-8*width_4B -: width_2B];
assign cont_2B[6] = phv_in[PHV_LEN-1-8*width_6B-8*width_4B- width_2B -: width_2B];
assign cont_2B[5] = phv_in[PHV_LEN-1-8*width_6B-8*width_4B-2*width_2B -: width_2B];
assign cont_2B[4] = phv_in[PHV_LEN-1-8*width_6B-8*width_4B-3*width_2B -: width_2B];
assign cont_2B[3] = phv_in[PHV_LEN-1-8*width_6B-8*width_4B-4*width_2B -: width_2B];
assign cont_2B[2] = phv_in[PHV_LEN-1-8*width_6B-8*width_4B-5*width_2B -: width_2B];
assign cont_2B[1] = phv_in[PHV_LEN-1-8*width_6B-8*width_4B-6*width_2B -: width_2B];
assign cont_2B[0] = phv_in[PHV_LEN-1-8*width_6B-8*width_4B-7*width_2B -: width_2B];
// Tao: get action for each PHV container
assign sub_action[24] = action_in[ACT_LEN*25-1-:ACT_LEN]; // 1st action
assign sub_action[23] = action_in[ACT_LEN*25-1 - ACT_LEN-:ACT_LEN]; // 2nd action
assign sub_action[22] = action_in[ACT_LEN*25-1 -2*ACT_LEN-:ACT_LEN]; // 3rd action
assign sub_action[21] = action_in[ACT_LEN*25-1 -3*ACT_LEN-:ACT_LEN];
assign sub_action[20] = action_in[ACT_LEN*25-1 -4*ACT_LEN-:ACT_LEN];
assign sub_action[19] = action_in[ACT_LEN*25-1 -5*ACT_LEN-:ACT_LEN];
assign sub_action[18] = action_in[ACT_LEN*25-1 -6*ACT_LEN-:ACT_LEN];
assign sub_action[17] = action_in[ACT_LEN*25-1 -7*ACT_LEN-:ACT_LEN];
assign sub_action[16] = action_in[ACT_LEN*25-1 -8*ACT_LEN-:ACT_LEN];
assign sub_action[15] = action_in[ACT_LEN*25-1 -9*ACT_LEN-:ACT_LEN];
assign sub_action[14] = action_in[ACT_LEN*25-1 -10*ACT_LEN-:ACT_LEN];
assign sub_action[13] = action_in[ACT_LEN*25-1 -11*ACT_LEN-:ACT_LEN];
assign sub_action[12] = action_in[ACT_LEN*25-1 -12*ACT_LEN-:ACT_LEN];
assign sub_action[11] = action_in[ACT_LEN*25-1 -13*ACT_LEN-:ACT_LEN];
assign sub_action[10] = action_in[ACT_LEN*25-1 -14*ACT_LEN-:ACT_LEN];
assign sub_action[9] = action_in[ACT_LEN*25-1 -15*ACT_LEN-:ACT_LEN];
assign sub_action[8] = action_in[ACT_LEN*25-1 -16*ACT_LEN-:ACT_LEN];
assign sub_action[7] = action_in[ACT_LEN*25-1 -17*ACT_LEN-:ACT_LEN];
assign sub_action[6] = action_in[ACT_LEN*25-1 -18*ACT_LEN-:ACT_LEN];
assign sub_action[5] = action_in[ACT_LEN*25-1 -19*ACT_LEN-:ACT_LEN];
assign sub_action[4] = action_in[ACT_LEN*25-1 -20*ACT_LEN-:ACT_LEN];
assign sub_action[3] = action_in[ACT_LEN*25-1 -21*ACT_LEN-:ACT_LEN];
assign sub_action[2] = action_in[ACT_LEN*25-1 -22*ACT_LEN-:ACT_LEN];
assign sub_action[1] = action_in[ACT_LEN*25-1 -23*ACT_LEN-:ACT_LEN];
assign sub_action[0] = action_in[ACT_LEN*25-1 -24*ACT_LEN-:ACT_LEN];
//assign inputs for ALUs
always @(posedge clk) begin
action_out <= action_in;
action_valid_out <= action_in_valid;
end
localparam IDLE = 0,
PROCESS = 1,
HALT = 2;
reg [2:0] state;
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
// phv_reg <= 1124'b0;
// action_full_reg <= 625'b0;
// phv_valid_reg <= 1'b0;
// action_valid_reg <= 1'b0;
//reset outputs
alu_in_valid <= 1'b0;
phv_remain_data <= 256'b0;
//reset all the outputs
alu_in_6B_1 <= 384'b0;
alu_in_6B_2 <= 384'b0;
alu_in_4B_1 <= 256'b0;
alu_in_4B_2 <= 256'b0;
alu_in_4B_3 <= 256'b0;
alu_in_2B_1 <= 128'b0;
alu_in_2B_2 <= 128'b0;
state <= IDLE;
ready_out <= 1;
end
else begin
case (state)
IDLE: begin
if(phv_in_valid == 1'b1) begin
if (ready_in) begin
alu_in_valid <= 1'b1;
end
else begin
ready_out <= 0;
state <= HALT;
end
//assign values one by one (of course need to consider act format)
for(i=7; i>=0; i=i-1) begin
case(sub_action[16+i+1][24:21])
//be noted that 2 ops need to be the same width
4'b0001, 4'b0010: begin
alu_in_6B_1[(i+1)*width_6B-1 -: width_6B] <= cont_6B[sub_action[16+i+1][18:16]];
alu_in_6B_2[(i+1)*width_6B-1 -: width_6B] <= cont_6B[sub_action[16+i+1][13:11]];
end
//extracted from action field (imm)
4'b1001, 4'b1010: begin
alu_in_6B_1[(i+1)*width_6B-1 -: width_6B] <= cont_6B[sub_action[16+i+1][18:16]];
alu_in_6B_2[(i+1)*width_6B-1 -: width_6B] <= {32'b0,sub_action[16+i+1][15:0]};
end
// set operation, operand A set to 0, operand B set to imm
4'b1110: begin
alu_in_6B_1[(i+1)*width_6B-1 -: width_6B] <= 48'b0;
alu_in_6B_2[(i+1)*width_6B-1 -: width_6B] <= {32'b0,sub_action[16+i+1][15:0]};
end
//if there is no action to take, output the original value
default: begin
//alu_1 should be set to the phv value
alu_in_6B_1[(i+1)*width_6B-1 -: width_6B] <= cont_6B[i];
alu_in_6B_2[(i+1)*width_6B-1 -: width_6B] <= 48'b0;
end
endcase
end
//4B is a bit of differernt from 2B and 6B
for(i=7; i>=0; i=i-1) begin
alu_in_4B_3[(i+1)*width_4B-1 -: width_4B] <= cont_4B[i];
casez(sub_action[8+i+1][24:21])
//be noted that 2 ops need to be the same width
4'b0001, 4'b0010: begin
alu_in_4B_1[(i+1)*width_4B-1 -: width_4B] <= cont_4B[sub_action[8+i+1][18:16]];
alu_in_4B_2[(i+1)*width_4B-1 -: width_4B] <= cont_4B[sub_action[8+i+1][13:11]];
end
4'b1001, 4'b1010: begin
alu_in_4B_1[(i+1)*width_4B-1 -: width_4B] <= cont_4B[sub_action[8+i+1][18:16]];
alu_in_4B_2[(i+1)*width_4B-1 -: width_4B] <= {16'b0,sub_action[8+i+1][15:0]};
end
// set operation, operand A set to 0, operand B set to imm
4'b1110: begin
alu_in_4B_1[(i+1)*width_4B-1 -: width_4B] <= 32'b0;
alu_in_4B_2[(i+1)*width_4B-1 -: width_4B] <= {16'b0,sub_action[8+i+1][15:0]};
end
//loadd put here
4'b1011, 4'b1000, 4'b0111: begin
alu_in_4B_1[(i+1)*width_4B-1 -: width_4B] <= cont_4B[sub_action[8+i+1][18:16]];
//alu_in_4B_2[(i+1)*width_4B-1 -: width_4B] <= {16'b0,sub_action[8+i+1][15:0]};
alu_in_4B_2[(i+1)*width_4B-1 -: width_4B] <= cont_4B[sub_action[8+i+1][13:11]];
end
//if there is no action to take, output the original value
default: begin
//alu_1 should be set to the phv value
alu_in_4B_1[(i+1)*width_4B-1 -: width_4B] <= cont_4B[i];
alu_in_4B_2[(i+1)*width_4B-1 -: width_4B] <= 32'b0;
end
endcase
end
for(i=7; i>=0; i=i-1) begin
casez(sub_action[i+1][24:21])
//be noted that 2 ops need to be the same width
4'b0001, 4'b0010: begin
alu_in_2B_1[(i+1)*width_2B-1 -: width_2B] <= cont_2B[sub_action[i+1][18:16]];
alu_in_2B_2[(i+1)*width_2B-1 -: width_2B] <= cont_2B[sub_action[i+1][13:11]];
end
4'b1001, 4'b1010: begin
alu_in_2B_1[(i+1)*width_2B-1 -: width_2B] <= cont_2B[sub_action[i+1][18:16]];
alu_in_2B_2[(i+1)*width_2B-1 -: width_2B] <= sub_action[i+1][15:0];
end
// set operation, operand A set to 0, operand B set to imm
4'b1110: begin
alu_in_2B_1[(i+1)*width_2B-1 -: width_2B] <= 16'b0;
alu_in_2B_2[(i+1)*width_2B-1 -: width_2B] <= sub_action[i+1][15:0];
end
//if there is no action to take, output the original value
default: begin
//alu_1 should be set to the phv value
alu_in_2B_1[(i+1)*width_2B-1 -: width_2B] <= cont_2B[i];
alu_in_2B_2[(i+1)*width_2B-1 -: width_2B] <= 16'b0;
end
endcase
end
//the left is metadata & conditional ins, no need to modify
phv_remain_data <= phv_in[255:0];
end
else begin
alu_in_valid <= 1'b0;
end
end
HALT: begin
if (ready_in) begin
alu_in_valid <= 1'b1;
state <= IDLE;
ready_out <= 1'b1;
end
end
endcase
end
end
endmodule
`timescale 1ns / 1ps
`define SUB_DEPARSE_1P(idx) \
if(parse_action[idx][0]) begin \
case(sub_depar_val_out_type_d1[idx]) \
2'b01: pkts_tdata_stored_1p_next[parse_action_ind_10b[idx]<<3 +: 16] = sub_depar_val_out_swapped[idx][32+:16]; \
2'b10: pkts_tdata_stored_1p_next[parse_action_ind_10b[idx]<<3 +: 32] = sub_depar_val_out_swapped[idx][16+:32]; \
2'b11: pkts_tdata_stored_1p_next[parse_action_ind_10b[idx]<<3 +: 48] = sub_depar_val_out_swapped[idx][0+:48]; \
endcase \
end \
`define SUB_DEPARSE_2P(idx) \
if(parse_action[idx][0]) begin \
case(sub_depar_val_out_type_d1[idx]) \
2'b01: pkts_tdata_stored_2p_next[parse_action_ind_10b[idx]<<3 +: 16] = sub_depar_val_out_swapped[idx][32+:16]; \
2'b10: pkts_tdata_stored_2p_next[parse_action_ind_10b[idx]<<3 +: 32] = sub_depar_val_out_swapped[idx][16+:32]; \
2'b11: pkts_tdata_stored_2p_next[parse_action_ind_10b[idx]<<3 +: 48] = sub_depar_val_out_swapped[idx][0+:48]; \
endcase \
end \
`define SWAP_BYTE_ORDER2(idx) \
assign sub_depar_val_out_swapped[idx] = { sub_depar_val_out_d1[idx][0+:8], \
sub_depar_val_out_d1[idx][8+:8], \
sub_depar_val_out_d1[idx][16+:8], \
sub_depar_val_out_d1[idx][24+:8], \
sub_depar_val_out_d1[idx][32+:8], \
sub_depar_val_out_d1[idx][40+:8]}; \
module depar_do_deparsing #(
parameter C_AXIS_DATA_WIDTH = 512,
parameter C_AXIS_TUSER_WIDTH = 128,
parameter C_PKT_VEC_WIDTH = (6+4+2)*8*8+256,
parameter DEPARSER_MOD_ID = 3'b101,
parameter C_VLANID_WIDTH = 12
)
(
input clk,
input aresetn,
// phv
input [C_PKT_VEC_WIDTH-1:0] phv_fifo_out,
input phv_fifo_empty,
output reg phv_fifo_rd_en,
//
input [C_VLANID_WIDTH-1:0] vlan_id,
input vlan_fifo_empty,
output reg vlan_fifo_rd_en,
//
input [C_AXIS_DATA_WIDTH-1:0] fst_half_fifo_tdata,
input [C_AXIS_TUSER_WIDTH-1:0] fst_half_fifo_tuser,
input [C_AXIS_DATA_WIDTH/8-1:0] fst_half_fifo_tkeep,
input fst_half_fifo_tlast,
input fst_half_fifo_empty,
output reg fst_half_fifo_rd_en,
//
input [C_AXIS_DATA_WIDTH-1:0] snd_half_fifo_tdata,
input [C_AXIS_TUSER_WIDTH-1:0] snd_half_fifo_tuser,
input [C_AXIS_DATA_WIDTH/8-1:0] snd_half_fifo_tkeep,
input snd_half_fifo_tlast,
input snd_half_fifo_empty,
output reg snd_half_fifo_rd_en,
//
input [C_AXIS_DATA_WIDTH-1:0] pkt_fifo_tdata,
input [C_AXIS_TUSER_WIDTH-1:0] pkt_fifo_tuser,
input [C_AXIS_DATA_WIDTH/8-1:0] pkt_fifo_tkeep,
input pkt_fifo_tlast,
input pkt_fifo_empty,
output reg pkt_fifo_rd_en,
// output
output reg [C_AXIS_DATA_WIDTH-1:0] depar_out_tdata,
output reg [C_AXIS_DATA_WIDTH/8-1:0] depar_out_tkeep,
output reg [C_AXIS_TUSER_WIDTH-1:0] depar_out_tuser,
output reg depar_out_tvalid,
output reg depar_out_tlast,
input depar_out_tready,
// control path
input [C_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata,
input [C_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser,
input [C_AXIS_DATA_WIDTH/8-1:0] ctrl_s_axis_tkeep,
input ctrl_s_axis_tvalid,
input ctrl_s_axis_tlast
);
integer i;
reg [C_AXIS_DATA_WIDTH-1:0] depar_out_tdata_next;
reg [C_AXIS_DATA_WIDTH/8-1:0] depar_out_tkeep_next;
reg [C_AXIS_TUSER_WIDTH-1:0] depar_out_tuser_next;
reg depar_out_tlast_next;
reg depar_out_tvalid_next;
wire [159:0] bram_out;
wire [6:0] parse_action_ind [0:9];
wire [9:0] parse_action_ind_10b [0:9];
wire [15:0] parse_action [0:9]; // we have 10 parse action
assign parse_action[9] = bram_out[0+:16];
assign parse_action[8] = bram_out[16+:16];
assign parse_action[7] = bram_out[32+:16];
assign parse_action[6] = bram_out[48+:16];
assign parse_action[5] = bram_out[64+:16];
assign parse_action[4] = bram_out[80+:16];
assign parse_action[3] = bram_out[96+:16];
assign parse_action[2] = bram_out[112+:16];
assign parse_action[1] = bram_out[128+:16];
assign parse_action[0] = bram_out[144+:16];
assign parse_action_ind[0] = parse_action[0][12:6];
assign parse_action_ind[1] = parse_action[1][12:6];
assign parse_action_ind[2] = parse_action[2][12:6];
assign parse_action_ind[3] = parse_action[3][12:6];
assign parse_action_ind[4] = parse_action[4][12:6];
assign parse_action_ind[5] = parse_action[5][12:6];
assign parse_action_ind[6] = parse_action[6][12:6];
assign parse_action_ind[7] = parse_action[7][12:6];
assign parse_action_ind[8] = parse_action[8][12:6];
assign parse_action_ind[9] = parse_action[9][12:6];
assign parse_action_ind_10b[0] = parse_action_ind[0];
assign parse_action_ind_10b[1] = parse_action_ind[1];
assign parse_action_ind_10b[2] = parse_action_ind[2];
assign parse_action_ind_10b[3] = parse_action_ind[3];
assign parse_action_ind_10b[4] = parse_action_ind[4];
assign parse_action_ind_10b[5] = parse_action_ind[5];
assign parse_action_ind_10b[6] = parse_action_ind[6];
assign parse_action_ind_10b[7] = parse_action_ind[7];
assign parse_action_ind_10b[8] = parse_action_ind[8];
assign parse_action_ind_10b[9] = parse_action_ind[9];
reg [9:0] sub_depar_act_valid;
wire [47:0] sub_depar_val_out_swapped [0:9];
wire [47:0] sub_depar_val_out [0:9];
wire [1:0] sub_depar_val_out_type [0:9];
wire [9:0] sub_depar_val_out_valid;
reg [47:0] sub_depar_val_out_d1 [0:9];
reg [1:0] sub_depar_val_out_type_d1 [0:9];
reg [9:0] sub_depar_val_out_valid_d1;
always @(posedge clk) begin
if (~aresetn) begin
for (i=0; i<10; i=i+1) begin
sub_depar_val_out_d1[i] <= 0;
sub_depar_val_out_type_d1[i] <= 0;
end
sub_depar_val_out_valid_d1 <= 0;
end
else begin
for (i=0; i<10; i=i+1) begin
sub_depar_val_out_d1[i] <= sub_depar_val_out[i];
sub_depar_val_out_type_d1[i] <= sub_depar_val_out_type[i];
end
sub_depar_val_out_valid_d1 <= sub_depar_val_out_valid;
end
end
`SWAP_BYTE_ORDER2(0)
`SWAP_BYTE_ORDER2(1)
`SWAP_BYTE_ORDER2(2)
`SWAP_BYTE_ORDER2(3)
`SWAP_BYTE_ORDER2(4)
`SWAP_BYTE_ORDER2(5)
`SWAP_BYTE_ORDER2(6)
`SWAP_BYTE_ORDER2(7)
`SWAP_BYTE_ORDER2(8)
`SWAP_BYTE_ORDER2(9)
wire discard_signal;
assign discard_signal = phv_fifo_out[128];
localparam IDLE=0,
WAIT_1CYCLE_RAM=1,
START_SUB_DEPARSE=2,
FINISH_SUB_DEPARSER_0=3,
FINISH_SUB_DEPARSER_1=4,
FINISH_SUB_DEPARSER_2=5,
FLUSH_PKT_0=6,
FLUSH_PKT_1=7,
FLUSH_PKT_2=8,
FLUSH_PKT_3=9,
FLUSH_PKT=10,
DROP_PKT=11,
DROP_PKT_REMAINING=12,
EMPTY_1=13,
EMPTY_2=14;
reg [C_AXIS_DATA_WIDTH-1:0] pkts_tdata_stored_1p, pkts_tdata_stored_2p;
reg [C_AXIS_TUSER_WIDTH-1:0] pkts_tuser_stored_1p, pkts_tuser_stored_2p;
reg [(C_AXIS_DATA_WIDTH/8)-1:0] pkts_tkeep_stored_1p, pkts_tkeep_stored_2p;
reg pkts_tlast_stored_1p, pkts_tlast_stored_2p;
reg [C_AXIS_DATA_WIDTH-1:0] pkts_tdata_stored_1p_next, pkts_tdata_stored_2p_next;
reg [C_AXIS_TUSER_WIDTH-1:0] pkts_tuser_stored_1p_next, pkts_tuser_stored_2p_next;
reg [(C_AXIS_DATA_WIDTH/8)-1:0] pkts_tkeep_stored_1p_next, pkts_tkeep_stored_2p_next;
reg pkts_tlast_stored_1p_next, pkts_tlast_stored_2p_next;
reg [4:0] state, state_next;
always @(*) begin
phv_fifo_rd_en = 0;
vlan_fifo_rd_en = 0;
fst_half_fifo_rd_en = 0;
snd_half_fifo_rd_en = 0;
pkt_fifo_rd_en = 0;
// output
depar_out_tdata_next = depar_out_tdata;
depar_out_tuser_next = depar_out_tuser;
depar_out_tkeep_next = depar_out_tkeep;
depar_out_tlast_next = depar_out_tlast;
depar_out_tvalid_next = 0;
sub_depar_act_valid = 10'b0;
state_next = state;
//
pkts_tdata_stored_1p_next = pkts_tdata_stored_1p;
pkts_tuser_stored_1p_next = pkts_tuser_stored_1p;
pkts_tkeep_stored_1p_next = pkts_tkeep_stored_1p;
pkts_tlast_stored_1p_next = pkts_tlast_stored_1p;
//
pkts_tdata_stored_2p_next = pkts_tdata_stored_2p;
pkts_tuser_stored_2p_next = pkts_tuser_stored_2p;
pkts_tkeep_stored_2p_next = pkts_tkeep_stored_2p;
pkts_tlast_stored_2p_next = pkts_tlast_stored_2p;
case (state)
IDLE: begin
if (!vlan_fifo_empty) begin
state_next = WAIT_1CYCLE_RAM;
end
end
WAIT_1CYCLE_RAM: begin
state_next = START_SUB_DEPARSE;
end
START_SUB_DEPARSE: begin
if (!fst_half_fifo_empty
&& !snd_half_fifo_empty
&& !phv_fifo_empty) begin
if (discard_signal == 1) begin
state_next = DROP_PKT;
phv_fifo_rd_en = 1;
end
else begin
sub_depar_act_valid = 10'b1111111111;
state_next = EMPTY_2;
pkts_tdata_stored_1p_next = fst_half_fifo_tdata;
pkts_tuser_stored_1p_next = phv_fifo_out[0+:128];
pkts_tkeep_stored_1p_next = fst_half_fifo_tkeep;
pkts_tlast_stored_1p_next = fst_half_fifo_tlast;
//
pkts_tdata_stored_2p_next = snd_half_fifo_tdata;
pkts_tuser_stored_2p_next = snd_half_fifo_tuser;
pkts_tkeep_stored_2p_next = snd_half_fifo_tkeep;
pkts_tlast_stored_2p_next = snd_half_fifo_tlast;
end
end
end
EMPTY_1: begin
// sub_depar_act_valid = 10'b1111111111;
state_next = EMPTY_2;
end
EMPTY_2: begin
state_next = FINISH_SUB_DEPARSER_0;
end
FINISH_SUB_DEPARSER_0: begin
`SUB_DEPARSE_1P(0)
`SUB_DEPARSE_1P(1)
`SUB_DEPARSE_2P(5)
state_next = FINISH_SUB_DEPARSER_1;
end
FINISH_SUB_DEPARSER_1: begin
`SUB_DEPARSE_1P(2)
`SUB_DEPARSE_2P(6)
`SUB_DEPARSE_2P(7)
state_next = FINISH_SUB_DEPARSER_2;
end
FINISH_SUB_DEPARSER_2: begin
`SUB_DEPARSE_1P(3)
`SUB_DEPARSE_1P(4)
`SUB_DEPARSE_2P(8)
`SUB_DEPARSE_2P(9)
state_next = FLUSH_PKT_0;
end
FLUSH_PKT_0: begin
phv_fifo_rd_en = 1;
vlan_fifo_rd_en = 1;
fst_half_fifo_rd_en = 1;
snd_half_fifo_rd_en = 1;
depar_out_tdata_next = pkts_tdata_stored_1p;
depar_out_tuser_next = pkts_tuser_stored_1p;
depar_out_tkeep_next = pkts_tkeep_stored_1p;
depar_out_tlast_next = pkts_tlast_stored_1p;
if (depar_out_tready) begin
depar_out_tvalid_next = 1;
if (pkts_tlast_stored_1p) begin
state_next = IDLE;
end
else begin
state_next = FLUSH_PKT_1;
end
end
end
FLUSH_PKT_1: begin
depar_out_tdata_next = pkts_tdata_stored_2p;
depar_out_tuser_next = pkts_tuser_stored_2p;
depar_out_tkeep_next = pkts_tkeep_stored_2p;
depar_out_tlast_next = pkts_tlast_stored_2p;
if (depar_out_tready) begin
depar_out_tvalid_next = 1;
if (pkts_tlast_stored_2p) begin
state_next = IDLE;
end
else begin
state_next = FLUSH_PKT;
end
end
end
FLUSH_PKT: begin
if (!pkt_fifo_empty) begin
depar_out_tdata_next = pkt_fifo_tdata;
depar_out_tuser_next = pkt_fifo_tuser;
depar_out_tkeep_next = pkt_fifo_tkeep;
depar_out_tlast_next = pkt_fifo_tlast;
if (depar_out_tready) begin
pkt_fifo_rd_en = 1;
depar_out_tvalid_next = 1;
if (pkt_fifo_tlast) begin
state_next = IDLE;
end
end
end
end
DROP_PKT: begin
if (fst_half_fifo_tlast==1
|| snd_half_fifo_tlast==1) begin
fst_half_fifo_rd_en = 1;
snd_half_fifo_rd_en = 1;
vlan_fifo_rd_en = 1;
state_next = IDLE;
end
else begin
fst_half_fifo_rd_en = 1;
snd_half_fifo_rd_en = 1;
vlan_fifo_rd_en = 1;
state_next = DROP_PKT_REMAINING;
end
end
DROP_PKT_REMAINING: begin
pkt_fifo_rd_en = 1;
if (pkt_fifo_tlast) begin
state_next = IDLE;
end
end
endcase
end
always @(posedge clk) begin
if (~aresetn) begin
state <= IDLE;
//
pkts_tdata_stored_1p <= 0;
pkts_tuser_stored_1p <= 0;
pkts_tkeep_stored_1p <= 0;
pkts_tlast_stored_1p <= 0;
//
pkts_tdata_stored_2p <= 0;
pkts_tuser_stored_2p <= 0;
pkts_tkeep_stored_2p <= 0;
pkts_tlast_stored_2p <= 0;
//
depar_out_tdata <= 0;
depar_out_tkeep <= 0;
depar_out_tuser <= 0;
depar_out_tlast <= 0;
depar_out_tvalid <= 0;
end
else begin
state <= state_next;
//
pkts_tdata_stored_1p <= pkts_tdata_stored_1p_next;
pkts_tuser_stored_1p <= pkts_tuser_stored_1p_next;
pkts_tkeep_stored_1p <= pkts_tkeep_stored_1p_next;
pkts_tlast_stored_1p <= pkts_tlast_stored_1p_next;
//
pkts_tdata_stored_2p <= pkts_tdata_stored_2p_next;
pkts_tuser_stored_2p <= pkts_tuser_stored_2p_next;
pkts_tkeep_stored_2p <= pkts_tkeep_stored_2p_next;
pkts_tlast_stored_2p <= pkts_tlast_stored_2p_next;
//
depar_out_tdata <= depar_out_tdata_next;
depar_out_tkeep <= depar_out_tkeep_next;
depar_out_tuser <= depar_out_tuser_next;
depar_out_tlast <= depar_out_tlast_next;
depar_out_tvalid <= depar_out_tvalid_next;
end
end
//===================== sub deparser
generate
genvar index;
for (index=0; index<10; index=index+1)
begin: sub_op
sub_deparser #(
.C_PKT_VEC_WIDTH(),
.C_PARSE_ACT_LEN()
)
sub_deparser (
.clk (clk),
.aresetn (aresetn),
.parse_act_valid (sub_depar_act_valid[index]),
.parse_act (parse_action[index][5:0]),
.phv_in (phv_fifo_out),
.val_out_valid (sub_depar_val_out_valid[index]),
.val_out (sub_depar_val_out[index]),
.val_out_type (sub_depar_val_out_type[index])
);
end
endgenerate
/*================Control Path====================*/
wire [7:0] mod_id; //module ID
wire [15:0] control_flag; //dst udp port num
reg [7:0] c_index; //table index(addr)
reg c_wr_en; //enable table write(wen)
reg [159:0] entry_reg;
reg [2:0] c_state;
localparam IDLE_C = 1,
WRITE_C = 2,
SU_WRITE_C = 3;
assign mod_id = ctrl_s_axis_tdata[368+:8];
assign control_flag = ctrl_s_axis_tdata[335:320];
//LE to BE switching
wire[C_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_swapped;
assign ctrl_s_axis_tdata_swapped = {ctrl_s_axis_tdata[0+:8],
ctrl_s_axis_tdata[8+:8],
ctrl_s_axis_tdata[16+:8],
ctrl_s_axis_tdata[24+:8],
ctrl_s_axis_tdata[32+:8],
ctrl_s_axis_tdata[40+:8],
ctrl_s_axis_tdata[48+:8],
ctrl_s_axis_tdata[56+:8],
ctrl_s_axis_tdata[64+:8],
ctrl_s_axis_tdata[72+:8],
ctrl_s_axis_tdata[80+:8],
ctrl_s_axis_tdata[88+:8],
ctrl_s_axis_tdata[96+:8],
ctrl_s_axis_tdata[104+:8],
ctrl_s_axis_tdata[112+:8],
ctrl_s_axis_tdata[120+:8],
ctrl_s_axis_tdata[128+:8],
ctrl_s_axis_tdata[136+:8],
ctrl_s_axis_tdata[144+:8],
ctrl_s_axis_tdata[152+:8],
ctrl_s_axis_tdata[160+:8],
ctrl_s_axis_tdata[168+:8],
ctrl_s_axis_tdata[176+:8],
ctrl_s_axis_tdata[184+:8],
ctrl_s_axis_tdata[192+:8],
ctrl_s_axis_tdata[200+:8],
ctrl_s_axis_tdata[208+:8],
ctrl_s_axis_tdata[216+:8],
ctrl_s_axis_tdata[224+:8],
ctrl_s_axis_tdata[232+:8],
ctrl_s_axis_tdata[240+:8],
ctrl_s_axis_tdata[248+:8],
ctrl_s_axis_tdata[256+:8],
ctrl_s_axis_tdata[264+:8],
ctrl_s_axis_tdata[272+:8],
ctrl_s_axis_tdata[280+:8],
ctrl_s_axis_tdata[288+:8],
ctrl_s_axis_tdata[296+:8],
ctrl_s_axis_tdata[304+:8],
ctrl_s_axis_tdata[312+:8],
ctrl_s_axis_tdata[320+:8],
ctrl_s_axis_tdata[328+:8],
ctrl_s_axis_tdata[336+:8],
ctrl_s_axis_tdata[344+:8],
ctrl_s_axis_tdata[352+:8],
ctrl_s_axis_tdata[360+:8],
ctrl_s_axis_tdata[368+:8],
ctrl_s_axis_tdata[376+:8],
ctrl_s_axis_tdata[384+:8],
ctrl_s_axis_tdata[392+:8],
ctrl_s_axis_tdata[400+:8],
ctrl_s_axis_tdata[408+:8],
ctrl_s_axis_tdata[416+:8],
ctrl_s_axis_tdata[424+:8],
ctrl_s_axis_tdata[432+:8],
ctrl_s_axis_tdata[440+:8],
ctrl_s_axis_tdata[448+:8],
ctrl_s_axis_tdata[456+:8],
ctrl_s_axis_tdata[464+:8],
ctrl_s_axis_tdata[472+:8],
ctrl_s_axis_tdata[480+:8],
ctrl_s_axis_tdata[488+:8],
ctrl_s_axis_tdata[496+:8],
ctrl_s_axis_tdata[504+:8]
};
always @(posedge clk or negedge aresetn) begin
if(~aresetn) begin
c_wr_en <= 1'b0;
c_index <= 4'b0;
entry_reg <= 0;
c_state <= IDLE_C;
end
else begin
case(c_state)
IDLE_C: begin
if(ctrl_s_axis_tvalid && mod_id[2:0] == DEPARSER_MOD_ID && control_flag == 16'hf2f1)begin
c_wr_en <= 1'b0;
c_index <= ctrl_s_axis_tdata[384+:8];
c_state <= WRITE_C;
end
else begin
c_wr_en <= 1'b0;
c_index <= 4'b0;
entry_reg <= 0;
c_state <= IDLE_C;
end
end
//support full table flush
WRITE_C: begin
if(ctrl_s_axis_tvalid) begin
c_wr_en <= 1'b1;
entry_reg <= ctrl_s_axis_tdata_swapped[511 -: 160];
if(ctrl_s_axis_tlast) begin
c_state <= IDLE_C;
end
else begin
c_state <= SU_WRITE_C;
end
end
else begin
c_wr_en <= 1'b0;
end
end
SU_WRITE_C: begin
if(ctrl_s_axis_tvalid) begin
entry_reg <= ctrl_s_axis_tdata_swapped[511 -: 160];
c_wr_en <= 1'b1;
c_index <= c_index + 1'b1;
if(ctrl_s_axis_tlast) begin
c_state <= IDLE_C;
end
else begin
c_state <= SU_WRITE_C;
end
end
else begin
c_wr_en <= 1'b0;
end
end
endcase
end
end
parse_act_ram_ip
parse_act_ram
(
// write port
.clka (clk),
.addra (c_index[4:0]),
.dina (entry_reg),
.ena (1'b1),
.wea (c_wr_en),
//
.clkb (clk),
.addrb (vlan_id[8:4]), // TODO: note that we may change due to little or big endian
.doutb (bram_out),
.enb (1'b1) // always set to 1
);
endmodule
`timescale 1ns / 1ps
module depar_wait_segs #(
parameter C_AXIS_DATA_WIDTH = 512,
parameter C_AXIS_TUSER_WIDTH = 128
)
(
input clk,
input aresetn,
// input from pkt fifo
input [C_AXIS_DATA_WIDTH-1:0] pkt_fifo_tdata,
input [C_AXIS_TUSER_WIDTH-1:0] pkt_fifo_tuser,
input [C_AXIS_DATA_WIDTH/8-1:0] pkt_fifo_tkeep,
input pkt_fifo_tlast,
input pkt_fifo_empty,
input fst_half_fifo_ready,
input snd_half_fifo_ready,
// output
output reg pkt_fifo_rd_en,
output reg [11:0] vlan,
output reg vlan_valid,
output reg [C_AXIS_DATA_WIDTH-1:0] fst_half_tdata,
output reg [C_AXIS_TUSER_WIDTH-1:0] fst_half_tuser,
output reg [C_AXIS_DATA_WIDTH/8-1:0] fst_half_tkeep,
output reg fst_half_tlast,
output reg fst_half_valid,
output reg [C_AXIS_DATA_WIDTH-1:0] snd_half_tdata,
output reg [C_AXIS_TUSER_WIDTH-1:0] snd_half_tuser,
output reg [C_AXIS_DATA_WIDTH/8-1:0] snd_half_tkeep,
output reg snd_half_tlast,
output reg snd_half_valid,
// output remaining segs to FIFO
output reg [C_AXIS_DATA_WIDTH-1:0] output_fifo_tdata,
output reg [C_AXIS_TUSER_WIDTH-1:0] output_fifo_tuser,
output reg [C_AXIS_DATA_WIDTH/8-1:0] output_fifo_tkeep,
output reg output_fifo_tlast,
output reg output_fifo_valid,
input output_fifo_ready
);
localparam WAIT_FIRST_SEG=0,
WAIT_SECOND_SEG=1,
EMPTY_1=2,
EMPTY_2=3,
FLUSH_SEG=4;
reg [C_AXIS_DATA_WIDTH-1:0] output_fifo_tdata_next;
reg [C_AXIS_TUSER_WIDTH-1:0] output_fifo_tuser_next;
reg [C_AXIS_DATA_WIDTH/8-1:0] output_fifo_tkeep_next;
reg output_fifo_tlast_next;
reg output_fifo_valid_next;
reg [C_AXIS_DATA_WIDTH-1:0] fst_half_tdata_next, snd_half_tdata_next;
reg [C_AXIS_TUSER_WIDTH-1:0] fst_half_tuser_next, snd_half_tuser_next;
reg [C_AXIS_DATA_WIDTH/8-1:0] fst_half_tkeep_next, snd_half_tkeep_next;
reg fst_half_tlast_next, snd_half_tlast_next;
reg fst_half_valid_next, snd_half_valid_next;
reg vlan_valid_next;
reg [11:0] vlan_next;
reg [2:0] state, state_next;
// we delay the processing of PHV to the next module
always @(*) begin
state_next = state;
pkt_fifo_rd_en = 0;
fst_half_tdata_next = 0;
fst_half_tuser_next = 0;
fst_half_tkeep_next = 0;
fst_half_tlast_next = 0;
snd_half_tdata_next = 0;
snd_half_tuser_next = 0;
snd_half_tkeep_next = 0;
snd_half_tlast_next = 0;
fst_half_valid_next = 0;
snd_half_valid_next = 0;
vlan_valid_next = 0;
vlan_next = vlan;
// output remaining segs
output_fifo_tdata_next = 0;
output_fifo_tuser_next = 0;
output_fifo_tkeep_next = 0;
output_fifo_tlast_next = 0;
output_fifo_valid_next = 0;
case (state)
WAIT_FIRST_SEG: begin
if (!pkt_fifo_empty) begin
fst_half_tdata_next = pkt_fifo_tdata;
fst_half_tuser_next = pkt_fifo_tuser;
fst_half_tkeep_next = pkt_fifo_tkeep;
fst_half_tlast_next = pkt_fifo_tlast;
vlan_next = pkt_fifo_tdata[116+:12];
if (pkt_fifo_tlast) begin
if (fst_half_fifo_ready && snd_half_fifo_ready) begin
pkt_fifo_rd_en = 1;
fst_half_valid_next = 1;
snd_half_valid_next = 1;
vlan_valid_next = 1;
state_next = WAIT_FIRST_SEG;
end
end
else begin
if (fst_half_fifo_ready) begin
pkt_fifo_rd_en = 1;
fst_half_valid_next = 1;
vlan_valid_next = 1;
state_next = WAIT_SECOND_SEG;
end
end
end
end
WAIT_SECOND_SEG: begin
if (!pkt_fifo_empty) begin
snd_half_tdata_next = pkt_fifo_tdata;
snd_half_tuser_next = pkt_fifo_tuser;
snd_half_tkeep_next = pkt_fifo_tkeep;
snd_half_tlast_next = pkt_fifo_tlast;
if (pkt_fifo_tlast) begin
if (snd_half_fifo_ready) begin
pkt_fifo_rd_en = 1;
snd_half_valid_next = 1;
state_next = WAIT_FIRST_SEG;
end
end
else begin
if (snd_half_fifo_ready) begin
pkt_fifo_rd_en = 1;
snd_half_valid_next = 1;
state_next = FLUSH_SEG;
end
end
end
end
FLUSH_SEG: begin
if (!pkt_fifo_empty) begin
output_fifo_tdata_next = pkt_fifo_tdata;
output_fifo_tuser_next = pkt_fifo_tuser;
output_fifo_tkeep_next = pkt_fifo_tkeep;
output_fifo_tlast_next = pkt_fifo_tlast;
if (output_fifo_ready) begin
output_fifo_valid_next = 1;
pkt_fifo_rd_en = 1;
if (pkt_fifo_tlast) begin
state_next = WAIT_FIRST_SEG;
end
end
end
end
endcase
end
always @(posedge clk) begin
if (~aresetn) begin
state <= WAIT_FIRST_SEG;
fst_half_tdata <= 0;
fst_half_tuser <= 0;
fst_half_tkeep <= 0;
fst_half_tlast <= 0;
snd_half_tdata <= 0;
snd_half_tuser <= 0;
snd_half_tkeep <= 0;
snd_half_tlast <= 0;
fst_half_valid <= 0;
snd_half_valid <= 0;
vlan_valid <= 0;
vlan <= 0;
//
output_fifo_tdata <= 0;
output_fifo_tuser <= 0;
output_fifo_tkeep <= 0;
output_fifo_tlast <= 0;
output_fifo_valid <= 0;
end
else begin
state <= state_next;
fst_half_tdata <= fst_half_tdata_next;
fst_half_tuser <= fst_half_tuser_next;
fst_half_tkeep <= fst_half_tkeep_next;
fst_half_tlast <= fst_half_tlast_next;
snd_half_tdata <= snd_half_tdata_next;
snd_half_tuser <= snd_half_tuser_next;
snd_half_tkeep <= snd_half_tkeep_next;
snd_half_tlast <= snd_half_tlast_next;
fst_half_valid <= fst_half_valid_next;
snd_half_valid <= snd_half_valid_next;
vlan_valid <= vlan_valid_next;
vlan <= vlan_next;
//
output_fifo_tdata <= output_fifo_tdata_next;
output_fifo_tuser <= output_fifo_tuser_next;
output_fifo_tkeep <= output_fifo_tkeep_next;
output_fifo_tlast <= output_fifo_tlast_next;
output_fifo_valid <= output_fifo_valid_next;
end
end
endmodule
`timescale 1ns / 1ps
module deparser_top #(
parameter C_AXIS_DATA_WIDTH = 512,
parameter C_AXIS_TUSER_WIDTH = 128,
parameter C_PKT_VEC_WIDTH = (6+4+2)*8*8+256,
parameter DEPARSER_MOD_ID = 3'b101,
parameter C_VLANID_WIDTH = 12,
parameter C_FIFO_BITS_WIDTH = 4
)
(
input axis_clk,
input aresetn,
//
input [C_AXIS_DATA_WIDTH-1:0] pkt_fifo_tdata,
input [C_AXIS_DATA_WIDTH/8-1:0] pkt_fifo_tkeep,
input [C_AXIS_TUSER_WIDTH-1:0] pkt_fifo_tuser,
input pkt_fifo_tlast,
input pkt_fifo_empty,
output pkt_fifo_rd_en,
input [C_PKT_VEC_WIDTH-1:0] phv_fifo_out,
input phv_fifo_empty,
output phv_fifo_rd_en,
output [C_AXIS_DATA_WIDTH-1:0] depar_out_tdata,
output [C_AXIS_DATA_WIDTH/8-1:0] depar_out_tkeep,
output [C_AXIS_TUSER_WIDTH-1:0] depar_out_tuser,
output depar_out_tvalid,
output depar_out_tlast,
input depar_out_tready,
// control path
input [C_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata,
input [C_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser,
input [C_AXIS_DATA_WIDTH/8-1:0] ctrl_s_axis_tkeep,
input ctrl_s_axis_tvalid,
input ctrl_s_axis_tlast
);
wire [C_AXIS_DATA_WIDTH-1:0] fst_half_fifo_tdata_in, fst_half_fifo_tdata_out;
wire [C_AXIS_TUSER_WIDTH-1:0] fst_half_fifo_tuser_in, fst_half_fifo_tuser_out;
wire [C_AXIS_DATA_WIDTH/8-1:0] fst_half_fifo_tkeep_in, fst_half_fifo_tkeep_out;
wire fst_half_fifo_tlast_in, fst_half_fifo_tlast_out;
wire fst_half_fifo_empty;
wire fst_half_fifo_full;
wire fst_half_fifo_valid_in;
wire fst_half_fifo_rd_en;
reg [C_AXIS_DATA_WIDTH-1:0] fst_half_fifo_tdata_in_r;
reg [C_AXIS_TUSER_WIDTH-1:0] fst_half_fifo_tuser_in_r;
reg [C_AXIS_DATA_WIDTH/8-1:0] fst_half_fifo_tkeep_in_r;
reg fst_half_fifo_tlast_in_r;
reg fst_half_fifo_valid_in_r;
wire [C_AXIS_DATA_WIDTH-1:0] snd_half_fifo_tdata_in, snd_half_fifo_tdata_out;
wire [C_AXIS_TUSER_WIDTH-1:0] snd_half_fifo_tuser_in, snd_half_fifo_tuser_out;
wire [C_AXIS_DATA_WIDTH/8-1:0] snd_half_fifo_tkeep_in, snd_half_fifo_tkeep_out;
wire snd_half_fifo_tlast_in, snd_half_fifo_tlast_out;
wire snd_half_fifo_empty;
wire snd_half_fifo_full;
wire snd_half_fifo_valid_in;
wire snd_half_fifo_rd_en;
reg [C_AXIS_DATA_WIDTH-1:0] snd_half_fifo_tdata_in_r;
reg [C_AXIS_TUSER_WIDTH-1:0] snd_half_fifo_tuser_in_r;
reg [C_AXIS_DATA_WIDTH/8-1:0] snd_half_fifo_tkeep_in_r;
reg snd_half_fifo_tlast_in_r;
reg snd_half_fifo_valid_in_r;
fallthrough_small_fifo #(
.WIDTH(C_AXIS_DATA_WIDTH+C_AXIS_TUSER_WIDTH+C_AXIS_DATA_WIDTH/8+1),
.MAX_DEPTH_BITS(4)
)
fst_half_fifo (
.din ({fst_half_fifo_tdata_in_r, fst_half_fifo_tuser_in_r, fst_half_fifo_tkeep_in_r, fst_half_fifo_tlast_in_r}),
.wr_en (fst_half_fifo_valid_in_r),
// .din ({fst_half_fifo_tdata_in, fst_half_fifo_tuser_in, fst_half_fifo_tkeep_in, fst_half_fifo_tlast_in}),
// .wr_en (fst_half_fifo_valid_in),
//
.rd_en (fst_half_fifo_rd_en),
.dout ({fst_half_fifo_tdata_out, fst_half_fifo_tuser_out, fst_half_fifo_tkeep_out, fst_half_fifo_tlast_out}),
//
.full (),
.prog_full (),
.nearly_full (fst_half_fifo_full),
.empty (fst_half_fifo_empty),
.reset (~aresetn),
.clk (axis_clk)
);
fallthrough_small_fifo #(
.WIDTH(C_AXIS_DATA_WIDTH+C_AXIS_TUSER_WIDTH+C_AXIS_DATA_WIDTH/8+1),
.MAX_DEPTH_BITS(4)
)
snd_half_fifo (
.din ({snd_half_fifo_tdata_in_r, snd_half_fifo_tuser_in_r, snd_half_fifo_tkeep_in_r, snd_half_fifo_tlast_in_r}),
.wr_en (snd_half_fifo_valid_in_r),
// .din ({snd_half_fifo_tdata_in, snd_half_fifo_tuser_in, snd_half_fifo_tkeep_in, snd_half_fifo_tlast_in}),
// .wr_en (snd_half_fifo_valid_in),
//
.rd_en (snd_half_fifo_rd_en),
.dout ({snd_half_fifo_tdata_out, snd_half_fifo_tuser_out, snd_half_fifo_tkeep_out, snd_half_fifo_tlast_out}),
//
.full (),
.prog_full (),
.nearly_full (snd_half_fifo_full),
.empty (snd_half_fifo_empty),
.reset (~aresetn),
.clk (axis_clk)
);
//===============================================
wire [C_VLANID_WIDTH-1:0] vlan_fifo_in, vlan_fifo_out;
wire vlan_valid_in;
wire vlan_fifo_rd_en;
wire vlan_fifo_full;
wire vlan_fifo_empty;
// vlan fifo
fallthrough_small_fifo #(
.WIDTH(C_VLANID_WIDTH),
.MAX_DEPTH_BITS(5)
)
vlan_fifo (
.din (vlan_fifo_in),
.wr_en (vlan_valid_in),
//
.rd_en (vlan_fifo_rd_en),
.dout (vlan_fifo_out),
//
.full (),
.prog_full (),
.nearly_full (vlan_fifo_full),
.empty (vlan_fifo_empty),
.reset (~aresetn),
.clk (axis_clk)
);
wire [C_AXIS_DATA_WIDTH-1:0] seg_fifo_tdata_in, seg_fifo_tdata_out;
wire [C_AXIS_TUSER_WIDTH-1:0] seg_fifo_tuser_in, seg_fifo_tuser_out;
wire [C_AXIS_DATA_WIDTH/8-1:0] seg_fifo_tkeep_in, seg_fifo_tkeep_out;
wire seg_fifo_tlast_in, seg_fifo_tlast_out;
wire seg_fifo_valid_in;
wire seg_fifo_rd_en;
wire seg_fifo_full;
wire seg_fifo_empty;
reg [C_AXIS_DATA_WIDTH-1:0] seg_fifo_tdata_in_r;
reg [C_AXIS_TUSER_WIDTH-1:0] seg_fifo_tuser_in_r;
reg [C_AXIS_DATA_WIDTH/8-1:0] seg_fifo_tkeep_in_r;
reg seg_fifo_tlast_in_r;
reg seg_fifo_valid_in_r;
// seg fifo
fallthrough_small_fifo #(
.WIDTH(C_AXIS_DATA_WIDTH+C_AXIS_TUSER_WIDTH+C_AXIS_DATA_WIDTH/8+1),
.MAX_DEPTH_BITS(5)
)
seg_fifo (
.din ({seg_fifo_tdata_in_r, seg_fifo_tuser_in_r, seg_fifo_tkeep_in_r, seg_fifo_tlast_in_r}),
.wr_en (seg_fifo_valid_in_r),
// .din ({seg_fifo_tdata_in, seg_fifo_tuser_in, seg_fifo_tkeep_in, seg_fifo_tlast_in}),
// .wr_en (seg_fifo_valid_in),
//
.rd_en (seg_fifo_rd_en),
.dout ({seg_fifo_tdata_out, seg_fifo_tuser_out, seg_fifo_tkeep_out, seg_fifo_tlast_out}),
//
.full (),
.prog_full (),
.nearly_full (seg_fifo_full),
.empty (seg_fifo_empty),
.reset (~aresetn),
.clk (axis_clk)
);
//
depar_wait_segs #(
)
wait_segs
(
.clk (axis_clk),
.aresetn (aresetn),
.pkt_fifo_tdata (pkt_fifo_tdata),
.pkt_fifo_tuser (pkt_fifo_tuser),
.pkt_fifo_tkeep (pkt_fifo_tkeep),
.pkt_fifo_tlast (pkt_fifo_tlast),
.pkt_fifo_empty (pkt_fifo_empty),
.fst_half_fifo_ready (~fst_half_fifo_full),
.snd_half_fifo_ready (~snd_half_fifo_full),
.pkt_fifo_rd_en (pkt_fifo_rd_en),
.vlan (vlan_fifo_in),
.vlan_valid (vlan_valid_in),
.fst_half_tdata (fst_half_fifo_tdata_in),
.fst_half_tuser (fst_half_fifo_tuser_in),
.fst_half_tkeep (fst_half_fifo_tkeep_in),
.fst_half_tlast (fst_half_fifo_tlast_in),
.fst_half_valid (fst_half_fifo_valid_in),
//
.snd_half_tdata (snd_half_fifo_tdata_in),
.snd_half_tuser (snd_half_fifo_tuser_in),
.snd_half_tkeep (snd_half_fifo_tkeep_in),
.snd_half_tlast (snd_half_fifo_tlast_in),
.snd_half_valid (snd_half_fifo_valid_in),
//
.output_fifo_tdata (seg_fifo_tdata_in),
.output_fifo_tuser (seg_fifo_tuser_in),
.output_fifo_tkeep (seg_fifo_tkeep_in),
.output_fifo_tlast (seg_fifo_tlast_in),
.output_fifo_valid (seg_fifo_valid_in),
.output_fifo_ready (~seg_fifo_full)
);
//
depar_do_deparsing #(
.C_PKT_VEC_WIDTH(C_PKT_VEC_WIDTH),
.DEPARSER_MOD_ID(DEPARSER_MOD_ID)
)
do_deparsing
(
.clk (axis_clk),
.aresetn (aresetn),
// phv
.phv_fifo_out (phv_fifo_out),
.phv_fifo_empty (phv_fifo_empty),
.phv_fifo_rd_en (phv_fifo_rd_en),
// vlan
.vlan_id (vlan_fifo_out),
.vlan_fifo_empty (vlan_fifo_empty),
.vlan_fifo_rd_en (vlan_fifo_rd_en),
// first half
.fst_half_fifo_tdata (fst_half_fifo_tdata_out),
.fst_half_fifo_tuser (fst_half_fifo_tuser_out),
.fst_half_fifo_tkeep (fst_half_fifo_tkeep_out),
.fst_half_fifo_tlast (fst_half_fifo_tlast_out),
.fst_half_fifo_empty (fst_half_fifo_empty),
.fst_half_fifo_rd_en (fst_half_fifo_rd_en),
// second half
.snd_half_fifo_tdata (snd_half_fifo_tdata_out),
.snd_half_fifo_tuser (snd_half_fifo_tuser_out),
.snd_half_fifo_tkeep (snd_half_fifo_tkeep_out),
.snd_half_fifo_tlast (snd_half_fifo_tlast_out),
.snd_half_fifo_empty (snd_half_fifo_empty),
.snd_half_fifo_rd_en (snd_half_fifo_rd_en),
// segs
.pkt_fifo_tdata (seg_fifo_tdata_out),
.pkt_fifo_tuser (seg_fifo_tuser_out),
.pkt_fifo_tkeep (seg_fifo_tkeep_out),
.pkt_fifo_tlast (seg_fifo_tlast_out),
.pkt_fifo_empty (seg_fifo_empty),
.pkt_fifo_rd_en (seg_fifo_rd_en),
// output
.depar_out_tdata (depar_out_tdata),
.depar_out_tuser (depar_out_tuser),
.depar_out_tkeep (depar_out_tkeep),
.depar_out_tlast (depar_out_tlast),
.depar_out_tvalid (depar_out_tvalid),
.depar_out_tready (depar_out_tready),
// control path
.ctrl_s_axis_tdata (ctrl_s_axis_tdata),
.ctrl_s_axis_tuser (ctrl_s_axis_tuser),
.ctrl_s_axis_tkeep (ctrl_s_axis_tkeep),
.ctrl_s_axis_tvalid (ctrl_s_axis_tvalid),
.ctrl_s_axis_tlast (ctrl_s_axis_tlast)
);
always @(posedge axis_clk) begin
if (~aresetn) begin
//
fst_half_fifo_tdata_in_r <= 0;
fst_half_fifo_tuser_in_r <= 0;
fst_half_fifo_tkeep_in_r <= 0;
fst_half_fifo_tlast_in_r <= 0;
fst_half_fifo_valid_in_r <= 0;
//
snd_half_fifo_tdata_in_r <= 0;
snd_half_fifo_tuser_in_r <= 0;
snd_half_fifo_tkeep_in_r <= 0;
snd_half_fifo_tlast_in_r <= 0;
snd_half_fifo_valid_in_r <= 0;
//
seg_fifo_tdata_in_r <= 0;
seg_fifo_tuser_in_r <= 0;
seg_fifo_tkeep_in_r <= 0;
seg_fifo_tlast_in_r <= 0;
seg_fifo_valid_in_r <= 0;
end
else begin
//
fst_half_fifo_tdata_in_r <= fst_half_fifo_tdata_in;
fst_half_fifo_tuser_in_r <= fst_half_fifo_tuser_in;
fst_half_fifo_tkeep_in_r <= fst_half_fifo_tkeep_in;
fst_half_fifo_tlast_in_r <= fst_half_fifo_tlast_in;
fst_half_fifo_valid_in_r <= fst_half_fifo_valid_in;
//
snd_half_fifo_tdata_in_r <= snd_half_fifo_tdata_in;
snd_half_fifo_tuser_in_r <= snd_half_fifo_tuser_in;
snd_half_fifo_tkeep_in_r <= snd_half_fifo_tkeep_in;
snd_half_fifo_tlast_in_r <= snd_half_fifo_tlast_in;
snd_half_fifo_valid_in_r <= snd_half_fifo_valid_in;
//
seg_fifo_tdata_in_r <= seg_fifo_tdata_in;
seg_fifo_tuser_in_r <= seg_fifo_tuser_in;
seg_fifo_tkeep_in_r <= seg_fifo_tkeep_in;
seg_fifo_tlast_in_r <= seg_fifo_tlast_in;
seg_fifo_valid_in_r <= seg_fifo_valid_in;
end
end
endmodule
`timescale 1ns / 1ps
module key_extract #(
parameter C_S_AXIS_DATA_WIDTH = 512,
parameter C_S_AXIS_TUSER_WIDTH = 128,
parameter STAGE_ID = 0,
parameter PHV_LEN = 48*8+32*8+16*8+256,
parameter KEY_LEN = 48*2+32*2+16*2+1,
// format of KEY_OFF entry: |--3(6B)--|--3(6B)--|--3(4B)--|--3(4B)--|--3(2B)--|--3(2B)--|
parameter KEY_OFF = (3+3)*3+20,
parameter AXIL_WIDTH = 32,
parameter KEY_OFF_ADDR_WIDTH = 4,
parameter KEY_EX_ID = 1,
parameter C_VLANID_WIDTH = 12
)(
input clk,
input rst_n,
//
input [PHV_LEN-1:0] phv_in,
input phv_valid_in,
output ready_out,
// input from vlan fifo
input key_offset_valid,
input [KEY_OFF-1:0] key_offset_w,
input [KEY_LEN-1:0] key_mask_w,
// output PHV and key
output reg [PHV_LEN-1:0] phv_out,
output reg phv_valid_out,
output [KEY_LEN-1:0] key_out_masked,
output reg key_valid_out,
input ready_in
);
integer i;
localparam WIDTH_2B = 16;
localparam WIDTH_4B = 32;
localparam WIDTH_6B = 48;
//reg [KEY_LEN-1:0] key_out;
//24 fields to be retrived from the pkt header
reg [WIDTH_2B-1:0] cont_2B [0:7];
reg [WIDTH_4B-1:0] cont_4B [0:7];
reg [WIDTH_6B-1:0] cont_6B [0:7];
wire [19:0] com_op;
wire [47:0] com_op_1, com_op_2;
wire [47:0] com_op_1_val, com_op_2_val;
//
reg [KEY_OFF-1:0] key_offset_r;
//
reg [KEY_LEN-1:0] key_mask_out_r;
//
assign com_op = key_offset_r[0+:20];
assign com_op_1 = com_op[17]==1? {40'b0, com_op[16:9]} : com_op_1_val;
assign com_op_1_val = com_op[13:12]==2?cont_6B[com_op[11:9]][7:0]:
(com_op[13:12]==1?{16'b0, cont_4B[com_op[11:9]][7:0]}:
(com_op[13:12]==0?{32'b0, cont_2B[com_op[11:9]][7:0]}:0));
assign com_op_2 = com_op[8]==1? {40'b0, com_op[7:0]} : com_op_2_val;
assign com_op_2_val = com_op[4:3]==2?cont_6B[com_op[2:0]][7:0]:
(com_op[4:3]==1?{16'b0, cont_4B[com_op[2:0]][7:0]}:
(com_op[4:3]==0?{32'b0, cont_2B[com_op[2:0]][7:0]}:0));
localparam IDLE_S=0,
CYCLE_1=1;
reg [2:0] state, state_next;
reg [KEY_LEN-1:0] key_out;
// reg ready_out_next;
assign ready_out = 1;
assign key_out_masked = key_out&(~key_mask_out_r);
always @(posedge clk) begin
if (~rst_n) begin
key_out <= 0;
state <= IDLE_S;
for (i=0; i<8; i=i+1) begin
cont_6B[i] <= 0;
cont_4B[i] <= 0;
cont_2B[i] <= 0;
end
phv_out <= 0;
phv_valid_out <= 0;
key_valid_out <= 0;
key_offset_r <= 0;
key_mask_out_r <= 0;
end
else begin
case (state)
IDLE_S: begin
if (phv_valid_in) begin
key_offset_r <= key_offset_w;
key_mask_out_r <= key_mask_w;
phv_out <= phv_in;
cont_6B[7] <= phv_in[PHV_LEN-1 -: WIDTH_6B];
cont_6B[6] <= phv_in[PHV_LEN-1- WIDTH_6B -: WIDTH_6B];
cont_6B[5] <= phv_in[PHV_LEN-1-2*WIDTH_6B -: WIDTH_6B];
cont_6B[4] <= phv_in[PHV_LEN-1-3*WIDTH_6B -: WIDTH_6B];
cont_6B[3] <= phv_in[PHV_LEN-1-4*WIDTH_6B -: WIDTH_6B];
cont_6B[2] <= phv_in[PHV_LEN-1-5*WIDTH_6B -: WIDTH_6B];
cont_6B[1] <= phv_in[PHV_LEN-1-6*WIDTH_6B -: WIDTH_6B];
cont_6B[0] <= phv_in[PHV_LEN-1-7*WIDTH_6B -: WIDTH_6B];
cont_4B[7] <= phv_in[PHV_LEN-1-8*WIDTH_6B -: WIDTH_4B];
cont_4B[6] <= phv_in[PHV_LEN-1-8*WIDTH_6B- WIDTH_4B -: WIDTH_4B];
cont_4B[5] <= phv_in[PHV_LEN-1-8*WIDTH_6B-2*WIDTH_4B -: WIDTH_4B];
cont_4B[4] <= phv_in[PHV_LEN-1-8*WIDTH_6B-3*WIDTH_4B -: WIDTH_4B];
cont_4B[3] <= phv_in[PHV_LEN-1-8*WIDTH_6B-4*WIDTH_4B -: WIDTH_4B];
cont_4B[2] <= phv_in[PHV_LEN-1-8*WIDTH_6B-5*WIDTH_4B -: WIDTH_4B];
cont_4B[1] <= phv_in[PHV_LEN-1-8*WIDTH_6B-6*WIDTH_4B -: WIDTH_4B];
cont_4B[0] <= phv_in[PHV_LEN-1-8*WIDTH_6B-7*WIDTH_4B -: WIDTH_4B];
cont_2B[7] <= phv_in[PHV_LEN-1-8*WIDTH_6B-8*WIDTH_4B -: WIDTH_2B];
cont_2B[6] <= phv_in[PHV_LEN-1-8*WIDTH_6B-8*WIDTH_4B- WIDTH_2B -: WIDTH_2B];
cont_2B[5] <= phv_in[PHV_LEN-1-8*WIDTH_6B-8*WIDTH_4B-2*WIDTH_2B -: WIDTH_2B];
cont_2B[4] <= phv_in[PHV_LEN-1-8*WIDTH_6B-8*WIDTH_4B-3*WIDTH_2B -: WIDTH_2B];
cont_2B[3] <= phv_in[PHV_LEN-1-8*WIDTH_6B-8*WIDTH_4B-4*WIDTH_2B -: WIDTH_2B];
cont_2B[2] <= phv_in[PHV_LEN-1-8*WIDTH_6B-8*WIDTH_4B-5*WIDTH_2B -: WIDTH_2B];
cont_2B[1] <= phv_in[PHV_LEN-1-8*WIDTH_6B-8*WIDTH_4B-6*WIDTH_2B -: WIDTH_2B];
cont_2B[0] <= phv_in[PHV_LEN-1-8*WIDTH_6B-8*WIDTH_4B-7*WIDTH_2B -: WIDTH_2B];
state <= CYCLE_1;
end
else begin
phv_valid_out <= 0;
key_valid_out <= 0;
end
end
CYCLE_1: begin
key_out[KEY_LEN-1 -: WIDTH_6B] <= cont_6B[key_offset_r[KEY_OFF-1 -: 3]];
key_out[KEY_LEN-1- 1*WIDTH_6B -: WIDTH_6B] <= cont_6B[key_offset_r[KEY_OFF-1-1*3 -: 3]];
key_out[KEY_LEN-1- 2*WIDTH_6B -: WIDTH_4B] <= cont_4B[key_offset_r[KEY_OFF-1-2*3 -: 3]];
key_out[KEY_LEN-1- 2*WIDTH_6B - 1*WIDTH_4B -: WIDTH_4B] <= cont_4B[key_offset_r[KEY_OFF-1-3*3 -: 3]];
key_out[KEY_LEN-1- 2*WIDTH_6B - 2*WIDTH_4B -: WIDTH_2B] <= cont_2B[key_offset_r[KEY_OFF-1-4*3 -: 3]];
key_out[KEY_LEN-1- 2*WIDTH_6B - 2*WIDTH_4B - WIDTH_2B -: WIDTH_2B] <= cont_2B[key_offset_r[KEY_OFF-1-5*3 -: 3]];
case(com_op[19:18])
2'b00: begin
key_out[0] <= (com_op_1>com_op_2)?1'b1:1'b0;
end
2'b01: begin
key_out[0] <= (com_op_1>=com_op_2)?1'b1:1'b0;
end
2'b10: begin
key_out[0] <= (com_op_1==com_op_2)?1'b1:1'b0;
end
default: begin
key_out[0] <= 1'b1;
end
endcase
phv_valid_out <= 1;
key_valid_out <= 1;
state <= IDLE_S;
end
endcase
end
end
endmodule
`timescale 1ns / 1ps
module key_extract_top #(
parameter C_S_AXIS_DATA_WIDTH = 512,
parameter C_S_AXIS_TUSER_WIDTH = 128,
parameter STAGE_ID = 0,
parameter PHV_LEN = 48*8+32*8+16*8+256,
parameter KEY_LEN = 48*2+32*2+16*2+1,
// format of KEY_OFF entry: |--3(6B)--|--3(6B)--|--3(4B)--|--3(4B)--|--3(2B)--|--3(2B)--|
parameter KEY_OFF = (3+3)*3+20,
parameter AXIL_WIDTH = 32,
parameter KEY_OFF_ADDR_WIDTH = 4,
parameter KEY_EX_ID = 1,
parameter C_VLANID_WIDTH = 12
)(
input clk,
input rst_n,
//
input [PHV_LEN-1:0] phv_in,
input phv_valid_in,
output ready_out,
// input from vlan fifo
input [C_VLANID_WIDTH-1:0] vlan_in,
input vlan_in_valid,
output vlan_ready,
// output PHV and key
output [PHV_LEN-1:0] phv_out,
output phv_valid_out,
output [KEY_LEN-1:0] key_out_masked,
output key_valid_out,
input ready_in,
//control path
input [C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata,
input [C_S_AXIS_TUSER_WIDTH-1:0] c_s_axis_tuser,
input [C_S_AXIS_DATA_WIDTH/8-1:0] c_s_axis_tkeep,
input c_s_axis_tvalid,
input c_s_axis_tlast,
output reg [C_S_AXIS_DATA_WIDTH-1:0] c_m_axis_tdata,
output reg [C_S_AXIS_TUSER_WIDTH-1:0] c_m_axis_tuser,
output reg [C_S_AXIS_DATA_WIDTH/8-1:0] c_m_axis_tkeep,
output reg c_m_axis_tvalid,
output reg c_m_axis_tlast
);
wire [KEY_OFF-1:0] key_offset_w; // output from RAM
//
wire [KEY_LEN-1:0] key_mask_out_w; // output from RAM
//
wire extract_ready_out;
assign ready_out = extract_ready_out;
assign vlan_ready = extract_ready_out;
//
localparam BRAM_IDLE=0,
BRAM_CYCLE_1=1,
BRAM_CYCLE_2=2,
BRAM_CYCLE_3=3;
reg [2:0] bram_state, bram_state_next;
reg key_offset_valid, key_offset_valid_next;
always @(*) begin
bram_state_next = bram_state;
key_offset_valid_next = 0;
case (bram_state)
BRAM_IDLE: begin
if (vlan_in_valid) begin
bram_state_next = BRAM_CYCLE_1;
end
end
BRAM_CYCLE_1: begin
bram_state_next = BRAM_IDLE;
key_offset_valid_next = 1;
end
BRAM_CYCLE_2: begin
bram_state_next = BRAM_CYCLE_3;
end
BRAM_CYCLE_3: begin
bram_state_next = BRAM_IDLE;
end
endcase
end
always @(posedge clk) begin
if (~rst_n) begin
bram_state <= BRAM_IDLE;
key_offset_valid <= 0;
end
else begin
bram_state <= bram_state_next;
key_offset_valid <= key_offset_valid_next;
end
end
reg [PHV_LEN-1:0] phv_in_d1;
reg phv_valid_in_d1;
reg key_offset_valid_d1;
reg [KEY_OFF-1:0] key_offset_w_d1; // output from RAM
reg [KEY_LEN-1:0] key_mask_out_w_d1; // output from RAM
always @(posedge clk) begin
if (~rst_n) begin
phv_in_d1 <= 0;
phv_valid_in_d1 <= 0;
key_offset_valid_d1 <= 0;
key_offset_w_d1 <= 0;
key_mask_out_w_d1 <= 0;
end
else begin
phv_in_d1 <= phv_in;
phv_valid_in_d1 <= phv_valid_in;
key_offset_valid_d1 <= key_offset_valid;
key_offset_w_d1 <= key_offset_w;
key_mask_out_w_d1 <= key_mask_out_w;
end
end
//
key_extract #(
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.C_S_AXIS_TUSER_WIDTH(C_S_AXIS_TUSER_WIDTH),
.STAGE_ID(STAGE_ID),
.PHV_LEN(PHV_LEN),
.KEY_LEN(KEY_LEN),
.KEY_OFF(KEY_OFF)
)
extractor
(
.clk (clk),
.rst_n (rst_n),
.phv_in (phv_in_d1),
.phv_valid_in (phv_valid_in_d1),
.ready_out (extract_ready_out),
//
.key_offset_valid (key_offset_valid_d1),
.key_offset_w (key_offset_w_d1),
.key_mask_w (key_mask_out_w_d1),
// output
.phv_out (phv_out),
.phv_valid_out (phv_valid_out),
.key_out_masked (key_out_masked),
.key_valid_out (key_valid_out),
.ready_in (ready_in)
);
//======================================================================================
/****control path for 512b*****/
wire [7:0] mod_id; //module ID
wire [3:0] resv;
wire [15:0] control_flag; //dst udp port num
reg [7:0] c_index; //table index(addr)
reg c_wr_en_off; //enable table write(wena)
reg c_wr_en_mask;
reg [2:0] c_state;
localparam IDLE_C = 0,
PARSE_C = 1,
WRITE_OFF_C = 2,
SU_WRITE_OFF_C = 3,
WRITE_MASK_C = 4,
SU_WRITE_MASK_C = 5,
FLUSH_PKT_C = 6;
generate
if(C_S_AXIS_DATA_WIDTH == 512) begin
assign mod_id = c_s_axis_tdata[368+:8];
//4'b0 for key offset
//4'b1 for key mask
assign resv = c_s_axis_tdata[376+:4];
assign control_flag = c_s_axis_tdata[335:320];
reg [37:0] key_off_entry_reg;
reg [192:0] key_mask_entry_reg;
//LE to BE switching
wire[C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata_swapped;
assign c_s_axis_tdata_swapped = { c_s_axis_tdata[0+:8],
c_s_axis_tdata[8+:8],
c_s_axis_tdata[16+:8],
c_s_axis_tdata[24+:8],
c_s_axis_tdata[32+:8],
c_s_axis_tdata[40+:8],
c_s_axis_tdata[48+:8],
c_s_axis_tdata[56+:8],
c_s_axis_tdata[64+:8],
c_s_axis_tdata[72+:8],
c_s_axis_tdata[80+:8],
c_s_axis_tdata[88+:8],
c_s_axis_tdata[96+:8],
c_s_axis_tdata[104+:8],
c_s_axis_tdata[112+:8],
c_s_axis_tdata[120+:8],
c_s_axis_tdata[128+:8],
c_s_axis_tdata[136+:8],
c_s_axis_tdata[144+:8],
c_s_axis_tdata[152+:8],
c_s_axis_tdata[160+:8],
c_s_axis_tdata[168+:8],
c_s_axis_tdata[176+:8],
c_s_axis_tdata[184+:8],
c_s_axis_tdata[192+:8],
c_s_axis_tdata[200+:8],
c_s_axis_tdata[208+:8],
c_s_axis_tdata[216+:8],
c_s_axis_tdata[224+:8],
c_s_axis_tdata[232+:8],
c_s_axis_tdata[240+:8],
c_s_axis_tdata[248+:8],
c_s_axis_tdata[256+:8],
c_s_axis_tdata[264+:8],
c_s_axis_tdata[272+:8],
c_s_axis_tdata[280+:8],
c_s_axis_tdata[288+:8],
c_s_axis_tdata[296+:8],
c_s_axis_tdata[304+:8],
c_s_axis_tdata[312+:8],
c_s_axis_tdata[320+:8],
c_s_axis_tdata[328+:8],
c_s_axis_tdata[336+:8],
c_s_axis_tdata[344+:8],
c_s_axis_tdata[352+:8],
c_s_axis_tdata[360+:8],
c_s_axis_tdata[368+:8],
c_s_axis_tdata[376+:8],
c_s_axis_tdata[384+:8],
c_s_axis_tdata[392+:8],
c_s_axis_tdata[400+:8],
c_s_axis_tdata[408+:8],
c_s_axis_tdata[416+:8],
c_s_axis_tdata[424+:8],
c_s_axis_tdata[432+:8],
c_s_axis_tdata[440+:8],
c_s_axis_tdata[448+:8],
c_s_axis_tdata[456+:8],
c_s_axis_tdata[464+:8],
c_s_axis_tdata[472+:8],
c_s_axis_tdata[480+:8],
c_s_axis_tdata[488+:8],
c_s_axis_tdata[496+:8],
c_s_axis_tdata[504+:8]
};
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
c_wr_en_off <= 1'b0;
c_wr_en_mask <= 1'b0;
c_index <= 8'b0;
c_m_axis_tdata <= 0;
c_m_axis_tuser <= 0;
c_m_axis_tkeep <= 0;
c_m_axis_tvalid <= 0;
c_m_axis_tlast <= 0;
key_off_entry_reg <= 0;
key_mask_entry_reg <= 0;
c_state <= IDLE_C;
end
else begin
case(c_state)
IDLE_C: begin
if(c_s_axis_tvalid && mod_id[7:3] == STAGE_ID && mod_id[2:0] == KEY_EX_ID &&
control_flag == 16'hf2f1)begin
//c_wr_en <= 1'b1;
c_index <= c_s_axis_tdata[384+:8];
c_m_axis_tdata <= 0;
c_m_axis_tuser <= 0;
c_m_axis_tkeep <= 0;
c_m_axis_tvalid <= 0;
c_m_axis_tlast <= 0;
//c_state <= WRITE_C;
if(resv == 4'b0) begin
c_wr_en_off <= 1'b0;
c_state <= WRITE_OFF_C;
end
else begin
c_wr_en_mask <= 1'b0;
c_state <= WRITE_MASK_C;
end
end
else begin
c_wr_en_off <= 1'b0;
c_wr_en_mask <= 1'b0;
c_index <= 8'b0;
c_m_axis_tdata <= c_s_axis_tdata;
c_m_axis_tuser <= c_s_axis_tuser;
c_m_axis_tkeep <= c_s_axis_tkeep;
c_m_axis_tvalid <= c_s_axis_tvalid;
c_m_axis_tlast <= c_s_axis_tlast;
c_state <= IDLE_C;
end
end
//support full table flush
WRITE_OFF_C: begin
if(c_s_axis_tvalid) begin
key_off_entry_reg <= c_s_axis_tdata_swapped[511 -: 38];
c_wr_en_off <= 1'b1;
if(c_s_axis_tlast) begin
c_state <= IDLE_C;
end
else begin
c_state <= SU_WRITE_OFF_C;
end
end
else begin
c_wr_en_off <= 0;
end
end
SU_WRITE_OFF_C: begin
if(c_s_axis_tvalid) begin
key_off_entry_reg <= c_s_axis_tdata_swapped[511 -: 38];
c_wr_en_off <= 1'b1;
c_index <= c_index + 1'b1;
if(c_s_axis_tlast) begin
c_state <= IDLE_C;
end
else begin
c_state <= SU_WRITE_OFF_C;
end
end
else begin
c_wr_en_off <= 1'b0;
end
end
WRITE_MASK_C: begin
if(c_s_axis_tvalid) begin
key_mask_entry_reg <= c_s_axis_tdata_swapped[511 -: 193];
c_wr_en_mask <= 1'b1;
if(c_s_axis_tlast) begin
c_state <= IDLE_C;
end
else begin
c_state <= SU_WRITE_MASK_C;
end
end
else begin
c_wr_en_mask <= 0;
end
end
SU_WRITE_MASK_C: begin
if(c_s_axis_tvalid) begin
key_mask_entry_reg <= c_s_axis_tdata_swapped[511 -: 193];
c_wr_en_mask <= 1'b1;
c_index <= c_index + 1'b1;
if(c_s_axis_tlast) begin
c_state <= IDLE_C;
end
else begin
c_state <= SU_WRITE_MASK_C;
end
end
else begin
c_wr_en_mask <= 1'b0;
end
end
default: begin
c_wr_en_off <= 1'b0;
c_wr_en_mask <= 1'b0;
c_index <= 8'b0;
c_m_axis_tdata <= c_s_axis_tdata;
c_m_axis_tuser <= c_s_axis_tuser;
c_m_axis_tkeep <= c_s_axis_tkeep;
c_m_axis_tvalid <= c_s_axis_tvalid;
c_m_axis_tlast <= c_s_axis_tlast;
end
endcase
end
end
//ram for key extract
blk_mem_gen_2
key_ram_38w_32d
(
.addra(c_index[4:0]),
.clka(clk),
.dina(key_off_entry_reg),
.ena(1'b1),
.wea(c_wr_en_off),
//only [3:0] is needed for addressing
.addrb(vlan_in[8:4]),
.clkb(clk),
.doutb(key_offset_w),
.enb(1'b1)
);
blk_mem_gen_3
mask_ram_193w_32d
(
.addra(c_index[4:0]),
.clka(clk),
.dina(key_mask_entry_reg),
.ena(1'b1),
.wea(c_wr_en_mask),
//only [3:0] is needed for addressing
.addrb(vlan_in[8:4]),
.clkb(clk),
.doutb(key_mask_out_w),
.enb(1'b1)
);
end
else if(C_S_AXIS_DATA_WIDTH == 256) begin
wire[C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata_swapped;
assign c_s_axis_tdata_swapped = { c_s_axis_tdata[0+:8],
c_s_axis_tdata[8+:8],
c_s_axis_tdata[16+:8],
c_s_axis_tdata[24+:8],
c_s_axis_tdata[32+:8],
c_s_axis_tdata[40+:8],
c_s_axis_tdata[48+:8],
c_s_axis_tdata[56+:8],
c_s_axis_tdata[64+:8],
c_s_axis_tdata[72+:8],
c_s_axis_tdata[80+:8],
c_s_axis_tdata[88+:8],
c_s_axis_tdata[96+:8],
c_s_axis_tdata[104+:8],
c_s_axis_tdata[112+:8],
c_s_axis_tdata[120+:8],
c_s_axis_tdata[128+:8],
c_s_axis_tdata[136+:8],
c_s_axis_tdata[144+:8],
c_s_axis_tdata[152+:8],
c_s_axis_tdata[160+:8],
c_s_axis_tdata[168+:8],
c_s_axis_tdata[176+:8],
c_s_axis_tdata[184+:8],
c_s_axis_tdata[192+:8],
c_s_axis_tdata[200+:8],
c_s_axis_tdata[208+:8],
c_s_axis_tdata[216+:8],
c_s_axis_tdata[224+:8],
c_s_axis_tdata[232+:8],
c_s_axis_tdata[240+:8],
c_s_axis_tdata[248+:8]};
assign mod_id = c_s_axis_tdata[112+:8];
//4'b0 for key offset
//4'b1 for key mask
assign resv = c_s_axis_tdata[120+:4];
assign control_flag = c_s_axis_tdata[64+:16];
reg [7:0] c_index_next;
reg [2:0] c_state_next;
reg c_wr_en_off_next, c_wr_en_mask_next;
reg [37:0] key_off_entry_reg, key_off_entry_reg_next;
reg [192:0] key_mask_entry_reg, key_mask_entry_reg_next;
reg [C_S_AXIS_DATA_WIDTH-1:0] r_tdata, c_s_axis_tdata_d1;
reg [C_S_AXIS_TUSER_WIDTH-1:0] r_tuser, c_s_axis_tuser_d1;
reg [C_S_AXIS_DATA_WIDTH/8-1:0] r_tkeep, c_s_axis_tkeep_d1;
reg r_tlast, c_s_axis_tlast_d1;
reg r_tvalid, c_s_axis_tvalid_d1;
reg [C_S_AXIS_DATA_WIDTH-1:0] r_1st_tdata, r_1st_tdata_next;
reg [C_S_AXIS_TUSER_WIDTH-1:0] r_1st_tuser, r_1st_tuser_next;
reg [C_S_AXIS_DATA_WIDTH/8-1:0] r_1st_tkeep, r_1st_tkeep_next;
reg r_1st_tlast, r_1st_tlast_next;
reg r_1st_tvalid, r_1st_tvalid_next;
always @(*) begin
c_state_next = c_state;
r_tdata = 0;
r_tkeep = 0;
r_tuser = 0;
r_tlast = 0;
r_tvalid = 0;
r_1st_tdata_next = r_1st_tdata;
r_1st_tkeep_next = r_1st_tkeep;
r_1st_tuser_next = r_1st_tuser;
r_1st_tlast_next = r_1st_tlast;
r_1st_tvalid_next = r_1st_tvalid;
c_wr_en_mask_next = 0;
c_wr_en_off_next = 0;
c_index_next = c_index;
key_off_entry_reg_next = key_off_entry_reg;
key_mask_entry_reg_next = key_mask_entry_reg;
case (c_state)
IDLE_C: begin
r_tvalid = 0; // 1st segment
if (c_s_axis_tvalid) begin
// store 1st element
r_1st_tdata_next = c_s_axis_tdata;
r_1st_tuser_next = c_s_axis_tuser;
r_1st_tkeep_next = c_s_axis_tkeep;
r_1st_tlast_next = c_s_axis_tlast;
r_1st_tvalid_next = c_s_axis_tvalid;
c_state_next = PARSE_C;
end
end
PARSE_C: begin // 2nd segment
if (mod_id[7:3] == STAGE_ID && mod_id[2:0] == KEY_EX_ID &&
control_flag == 16'hf2f1 && c_s_axis_tvalid) begin
if (resv == 4'b0 && c_s_axis_tvalid) begin
c_index_next = c_s_axis_tdata[128+:8];
c_state_next = WRITE_OFF_C;
end
else begin
c_index_next = c_s_axis_tdata[128+:8];
c_state_next = WRITE_MASK_C;
end
end
else if (!c_s_axis_tvalid) begin
end
else begin
// emit
r_tdata = r_1st_tdata;
r_tkeep = r_1st_tkeep;
r_tuser = r_1st_tuser;
r_tlast = r_1st_tlast;
r_tvalid = r_1st_tvalid;
c_state_next = FLUSH_PKT_C;
end
end
WRITE_OFF_C: begin
if (c_s_axis_tvalid) begin
c_wr_en_off_next = 1;
key_off_entry_reg_next = c_s_axis_tdata_swapped[255-:38];
c_state_next = FLUSH_PKT_C;
end
end
WRITE_MASK_C: begin
if (c_s_axis_tvalid) begin
c_wr_en_mask_next = 1;
key_mask_entry_reg_next = c_s_axis_tdata_swapped[255-:193];
c_state_next = FLUSH_PKT_C;
end
end
FLUSH_PKT_C: begin
c_wr_en_off_next = 0;
c_wr_en_mask_next = 0;
r_tdata = c_s_axis_tdata_d1;
r_tkeep = c_s_axis_tkeep_d1;
r_tuser = c_s_axis_tuser_d1;
r_tlast = c_s_axis_tlast_d1;
r_tvalid = c_s_axis_tvalid_d1;
if (c_s_axis_tvalid_d1 && c_s_axis_tlast_d1) begin
c_state_next = IDLE_C;
end
end
endcase
end
always @(posedge clk) begin
if (~rst_n) begin
c_state <= IDLE_C;
// ctrl output
c_m_axis_tdata <= 0;
c_m_axis_tuser <= 0;
c_m_axis_tkeep <= 0;
c_m_axis_tlast <= 0;
c_m_axis_tvalid <= 0;
//
c_index <= 0;
c_wr_en_off <= 0;
c_wr_en_mask <= 0;
key_off_entry_reg <= 0;
key_mask_entry_reg <= 0;
end
else begin
c_state <= c_state_next;
// output ctrl master signals
c_m_axis_tdata <= r_tdata;
c_m_axis_tkeep <= r_tkeep;
c_m_axis_tuser <= r_tuser;
c_m_axis_tlast <= r_tlast;
c_m_axis_tvalid <= r_tvalid;
//
c_index <= c_index_next;
c_wr_en_off <= c_wr_en_off_next;
c_wr_en_mask <= c_wr_en_mask_next;
key_off_entry_reg <= key_off_entry_reg_next;
key_mask_entry_reg <= key_mask_entry_reg_next;
end
end
always @(posedge clk) begin
if (~rst_n) begin
// delayed 1 clk
c_s_axis_tdata_d1 <= 0;
c_s_axis_tuser_d1 <= 0;
c_s_axis_tkeep_d1 <= 0;
c_s_axis_tlast_d1 <= 0;
c_s_axis_tvalid_d1 <= 0;
//
r_1st_tdata <= 0;
r_1st_tkeep <= 0;
r_1st_tuser <= 0;
r_1st_tlast <= 0;
r_1st_tvalid <= 0;
end
else begin
// delayed 1 clk
c_s_axis_tdata_d1 <= c_s_axis_tdata;
c_s_axis_tuser_d1 <= c_s_axis_tuser;
c_s_axis_tkeep_d1 <= c_s_axis_tkeep;
c_s_axis_tlast_d1 <= c_s_axis_tlast;
c_s_axis_tvalid_d1 <= c_s_axis_tvalid;
//
r_1st_tdata <= r_1st_tdata_next;
r_1st_tkeep <= r_1st_tkeep_next;
r_1st_tuser <= r_1st_tuser_next;
r_1st_tlast <= r_1st_tlast_next;
r_1st_tvalid <= r_1st_tvalid_next;
end
end
//ram for key extract
//blk_mem_gen_2 act_ram_18w_16d
// blk_mem_gen_2 #(
// .C_INIT_FILE_NAME ("./key_extract.mif"),
// .C_LOAD_INIT_FILE (1)
// )
blk_mem_gen_2
key_ram_38w_32d
(
.addra(c_index[4:0]),
.clka(clk),
.dina(key_off_entry_reg),
.ena(1'b1),
.wea(c_wr_en_off),
//only [3:0] is needed for addressing
.addrb(vlan_in[8:4]),
.clkb(clk),
.doutb(key_offset_w),
.enb(1'b1)
);
blk_mem_gen_3
mask_ram_193w_16d
(
.addra(c_index[4:0]),
.clka(clk),
.dina(key_mask_entry_reg),
.ena(1'b1),
.wea(c_wr_en_mask),
//only [3:0] is needed for addressing
.addrb(vlan_in[8:4]),
.clkb(clk),
.doutb(key_mask_out_w),
.enb(1'b1)
);
end
endgenerate
//==========================================================
endmodule
`timescale 1ns / 1ps
module last_stage #(
parameter C_S_AXIS_DATA_WIDTH = 512,
parameter C_S_AXIS_TUSER_WIDTH = 128,
parameter STAGE_ID = 0, // valid: 0-4
parameter PHV_LEN = 48*8+32*8+16*8+256,
parameter KEY_LEN = 48*2+32*2+16*2+1,
parameter ACT_LEN = 25,
parameter KEY_OFF = 6*3+20,
parameter C_NUM_QUEUES = 4,
parameter C_VLANID_WIDTH = 12
)
(
input axis_clk,
input aresetn,
input [PHV_LEN-1:0] phv_in,
input phv_in_valid,
output stage_ready_out,
output vlan_ready_out,
input [C_VLANID_WIDTH-1:0] vlan_in,
input vlan_valid_in,
//
output reg [PHV_LEN-1:0] phv_out_0,
output reg phv_out_valid_0,
input phv_fifo_ready_0,
output reg [PHV_LEN-1:0] phv_out_1,
output reg phv_out_valid_1,
input phv_fifo_ready_1,
output reg [PHV_LEN-1:0] phv_out_2,
output reg phv_out_valid_2,
input phv_fifo_ready_2,
output reg [PHV_LEN-1:0] phv_out_3,
output reg phv_out_valid_3,
input phv_fifo_ready_3,
//control path
input [C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata,
input [C_S_AXIS_TUSER_WIDTH-1:0] c_s_axis_tuser,
input [C_S_AXIS_DATA_WIDTH/8-1:0] c_s_axis_tkeep,
input c_s_axis_tvalid,
input c_s_axis_tlast,
output [C_S_AXIS_DATA_WIDTH-1:0] c_m_axis_tdata,
output [C_S_AXIS_TUSER_WIDTH-1:0] c_m_axis_tuser,
output [C_S_AXIS_DATA_WIDTH/8-1:0] c_m_axis_tkeep,
output c_m_axis_tvalid,
output c_m_axis_tlast
);
//key_extract to lookup_engine
wire [KEY_LEN-1:0] key2lookup_key;
wire key2lookup_key_valid;
wire key2lookup_phv_valid;
wire [PHV_LEN-1:0] key2lookup_phv;
wire lookup2key_ready;
reg [KEY_LEN-1:0] key2lookup_key_r;
reg key2lookup_key_valid_r;
reg key2lookup_phv_valid_r;
reg [PHV_LEN-1:0] key2lookup_phv_r;
//control path 1 (key2lookup)
wire [C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata_1;
wire [((C_S_AXIS_DATA_WIDTH/8))-1:0] c_s_axis_tkeep_1;
wire [C_S_AXIS_TUSER_WIDTH-1:0] c_s_axis_tuser_1;
wire c_s_axis_tvalid_1;
wire c_s_axis_tlast_1;
//control path 2 (lkup2action)
wire [C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata_2;
wire [((C_S_AXIS_DATA_WIDTH/8))-1:0] c_s_axis_tkeep_2;
wire [C_S_AXIS_TUSER_WIDTH-1:0] c_s_axis_tuser_2;
wire c_s_axis_tvalid_2;
wire c_s_axis_tlast_2;
//lookup_engine to action_engine
wire [ACT_LEN*25-1:0] lookup2action_action;
wire lookup2action_action_valid;
wire [PHV_LEN-1:0] lookup2action_phv;
wire action2lookup_ready;
reg [ACT_LEN*25-1:0] lookup2action_action_r;
reg lookup2action_action_valid_r;
reg [PHV_LEN-1:0] lookup2action_phv_r;
wire [PHV_LEN-1:0] phv_out;
wire phv_out_valid_from_ae;
//
wire [C_VLANID_WIDTH-1:0] act_vlan_out;
wire act_vlan_out_valid;
reg [C_VLANID_WIDTH-1:0] act_vlan_out_r;
reg act_vlan_out_valid_r;
wire act_vlan_ready;
key_extract_top #(
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.C_S_AXIS_TUSER_WIDTH(C_S_AXIS_TUSER_WIDTH),
.STAGE_ID(STAGE_ID),
.PHV_LEN(),
.KEY_LEN(KEY_LEN),
// format of KEY_OFF entry: |--3(6B)--|--3(6B)--|--3(4B)--|--3(4B)--|--3(2B)--|--3(2B)--|
.KEY_OFF(KEY_OFF),
.AXIL_WIDTH(),
.KEY_OFF_ADDR_WIDTH(),
.KEY_EX_ID()
)key_extract(
.clk(axis_clk),
.rst_n(aresetn),
.phv_in(phv_in),
.phv_valid_in(phv_in_valid),
.ready_out(stage_ready_out),
// vlan
.vlan_in (vlan_in),
.vlan_in_valid (vlan_valid_in),
.vlan_ready (vlan_ready_out),
.phv_out(key2lookup_phv),
.phv_valid_out(key2lookup_phv_valid),
.key_out_masked(key2lookup_key),
.key_valid_out(key2lookup_key_valid),
.ready_in(lookup2key_ready),
//control path
.c_s_axis_tdata(c_s_axis_tdata),
.c_s_axis_tuser(c_s_axis_tuser),
.c_s_axis_tkeep(c_s_axis_tkeep),
.c_s_axis_tvalid(c_s_axis_tvalid),
.c_s_axis_tlast(c_s_axis_tlast),
.c_m_axis_tdata(c_s_axis_tdata_1),
.c_m_axis_tuser(c_s_axis_tuser_1),
.c_m_axis_tkeep(c_s_axis_tkeep_1),
.c_m_axis_tvalid(c_s_axis_tvalid_1),
.c_m_axis_tlast(c_s_axis_tlast_1)
);
lookup_engine_top #(
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.C_S_AXIS_TUSER_WIDTH(C_S_AXIS_TUSER_WIDTH),
.STAGE_ID(STAGE_ID),
.PHV_LEN(),
.KEY_LEN(KEY_LEN),
.ACT_LEN(),
.LOOKUP_ID()
) lookup_engine(
.clk(axis_clk),
.rst_n(aresetn),
//output from key extractor
.extract_key(key2lookup_key_r),
.key_valid(key2lookup_key_valid_r),
.phv_valid(key2lookup_phv_valid_r),
.phv_in(key2lookup_phv_r),
.ready_out(lookup2key_ready),
//output to the action engine
.action(lookup2action_action),
.action_valid(lookup2action_action_valid),
.phv_out(lookup2action_phv),
.ready_in(action2lookup_ready),
//
.act_vlan_out (act_vlan_out),
.act_vlan_valid_out (act_vlan_out_valid),
// .act_vlan_ready (act_vlan_ready),
.act_vlan_ready (action2lookup_ready),
//control path
.c_s_axis_tdata(c_s_axis_tdata_1),
.c_s_axis_tuser(c_s_axis_tuser_1),
.c_s_axis_tkeep(c_s_axis_tkeep_1),
.c_s_axis_tvalid(c_s_axis_tvalid_1),
.c_s_axis_tlast(c_s_axis_tlast_1),
.c_m_axis_tdata(c_s_axis_tdata_2),
.c_m_axis_tuser(c_s_axis_tuser_2),
.c_m_axis_tkeep(c_s_axis_tkeep_2),
.c_m_axis_tvalid(c_s_axis_tvalid_2),
.c_m_axis_tlast(c_s_axis_tlast_2)
);
action_engine #(
.STAGE_ID(STAGE_ID),
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.PHV_LEN(),
.ACT_LEN(),
.ACTION_ID()
)action_engine(
.clk(axis_clk),
.rst_n(aresetn),
//signals from lookup to ALUs
.phv_in(lookup2action_phv_r),
.phv_valid_in(lookup2action_action_valid_r),
.action_in(lookup2action_action_r),
.action_valid_in(lookup2action_action_valid_r),
.ready_out(action2lookup_ready),
//signals output from ALUs
.phv_out(phv_out),
.phv_valid_out(phv_out_valid_from_ae),
.ready_in(phv_fifo_ready_0||phv_fifo_ready_1||phv_fifo_ready_2||phv_fifo_ready_3),
.act_vlan_in (act_vlan_out_r),
.act_vlan_valid_in (act_vlan_out_valid_r),
.act_vlan_ready (act_vlan_ready),
// vlan
.vlan_out (),
.vlan_out_valid (),
.vlan_out_ready (),
//control path
.c_s_axis_tdata(c_s_axis_tdata_2),
.c_s_axis_tuser(c_s_axis_tuser_2),
.c_s_axis_tkeep(c_s_axis_tkeep_2),
.c_s_axis_tvalid(c_s_axis_tvalid_2),
.c_s_axis_tlast(c_s_axis_tlast_2),
.c_m_axis_tdata(c_m_axis_tdata),
.c_m_axis_tuser(c_m_axis_tuser),
.c_m_axis_tkeep(c_m_axis_tkeep),
.c_m_axis_tvalid(c_m_axis_tvalid),
.c_m_axis_tlast(c_m_axis_tlast)
);
// pkt_hdr_vec_next = {pkt_hdr_vec_w[PKT_HDR_LEN-1:145], p_cur_queue_val, pkt_hdr_vec_w[0+:141]};
// position: [141+:4]
//
reg [PHV_LEN-1:0] phv_out_0_next;
reg [PHV_LEN-1:0] phv_out_1_next;
reg [PHV_LEN-1:0] phv_out_2_next;
reg [PHV_LEN-1:0] phv_out_3_next;
reg phv_out_valid_0_next;
reg phv_out_valid_1_next;
reg phv_out_valid_2_next;
reg phv_out_valid_3_next;
always @(*) begin
phv_out_valid_0_next = 0;
phv_out_valid_1_next = 0;
phv_out_valid_2_next = 0;
phv_out_valid_3_next = 0;
phv_out_0_next = phv_out;
phv_out_1_next = phv_out;
phv_out_2_next = phv_out;
phv_out_3_next = phv_out;
if (phv_out_valid_from_ae) begin
if (phv_out[141]) begin
phv_out_valid_0_next = 1;
end
if (phv_out[142]) begin
phv_out_valid_1_next = 1;
end
if (phv_out[143]) begin
phv_out_valid_2_next = 1;
end
if (phv_out[144]) begin
phv_out_valid_3_next = 1;
end
end
end
always @(posedge axis_clk) begin
if (~aresetn) begin
phv_out_0 <= 0;
phv_out_1 <= 0;
phv_out_2 <= 0;
phv_out_3 <= 0;
phv_out_valid_0 <= 0;
phv_out_valid_1 <= 0;
phv_out_valid_2 <= 0;
phv_out_valid_3 <= 0;
end
else begin
phv_out_0 <= phv_out_0_next;
phv_out_1 <= phv_out_1_next;
phv_out_2 <= phv_out_2_next;
phv_out_3 <= phv_out_3_next;
phv_out_valid_0 <= phv_out_valid_0_next;
phv_out_valid_1 <= phv_out_valid_1_next;
phv_out_valid_2 <= phv_out_valid_2_next;
phv_out_valid_3 <= phv_out_valid_3_next;
end
end
always @(posedge axis_clk) begin
if (~aresetn) begin
key2lookup_key_r <= 0;
key2lookup_key_valid_r <= 0;
key2lookup_phv_valid_r <= 0;
key2lookup_phv_r <= 0;
lookup2action_action_r <= 0;
lookup2action_action_valid_r <= 0;
lookup2action_phv_r <= 0;
//
act_vlan_out_r <= 0;
act_vlan_out_valid_r <= 0;
end
else begin
key2lookup_key_r <= key2lookup_key;
key2lookup_key_valid_r <= key2lookup_key_valid;
key2lookup_phv_valid_r <= key2lookup_phv_valid;
key2lookup_phv_r <= key2lookup_phv;
lookup2action_action_r <= lookup2action_action;
lookup2action_action_valid_r <= lookup2action_action_valid;
lookup2action_phv_r <= lookup2action_phv;
//
act_vlan_out_r <= act_vlan_out;
act_vlan_out_valid_r <= act_vlan_out_valid;
end
end
endmodule
`timescale 1ns / 1ps
module lke_cam_part #(
parameter C_S_AXIS_DATA_WIDTH = 512,
parameter C_S_AXIS_TUSER_WIDTH = 128,
parameter STAGE_ID = 0,
parameter PHV_LEN = 48*8+32*8+16*8+256,
parameter KEY_LEN = 48*2+32*2+16*2+5,
parameter ACT_LEN = 625,
parameter LOOKUP_ID = 2,
parameter C_VLANID_WIDTH = 12
)
(
input clk,
input rst_n,
//output from key extractor
input [KEY_LEN-1:0] extract_key,
input key_valid,
input phv_valid,
input [PHV_LEN-1:0] phv_in,
output ready_out,
// output to the ram part
output reg [PHV_LEN-1:0] phv_out,
output reg phv_out_valid,
output reg [3:0] match_addr_out,
output reg if_match,
input ready_in,
//control path
input [C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata,
input [C_S_AXIS_TUSER_WIDTH-1:0] c_s_axis_tuser,
input [C_S_AXIS_DATA_WIDTH/8-1:0] c_s_axis_tkeep,
input c_s_axis_tvalid,
input c_s_axis_tlast,
output reg [C_S_AXIS_DATA_WIDTH-1:0] c_m_axis_tdata,
output reg [C_S_AXIS_TUSER_WIDTH-1:0] c_m_axis_tuser,
output reg [C_S_AXIS_DATA_WIDTH/8-1:0] c_m_axis_tkeep,
output reg c_m_axis_tvalid,
output reg c_m_axis_tlast
);
/********intermediate variables declared here********/
wire [3:0] match_addr;
wire match;
reg [PHV_LEN-1:0] phv_reg;
reg [2:0] lookup_state;
wire [11:0] vlan_id;
assign vlan_id = phv_in[140:129];
wire [204:0] dbg_input;
assign dbg_input = {vlan_id[3:0], vlan_id[11:4], extract_key};
/********intermediate variables declared here********/
//here, the output should be controlled.
localparam IDLE_S = 3'd0,
WAIT1_S = 3'd1,
WAIT2_S = 3'd2,
TRANS_S = 3'd3,
HALT_S = 3'd4,
EMPTY1_S = 3'd5,
OUTPUT_S = 3'd6;
assign ready_out = lookup_state!=HALT_S;
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
phv_reg <= 0;
lookup_state <= IDLE_S;
phv_out <= 0;
phv_out_valid <= 0;
match_addr_out <= 0;
if_match <= 0;
// ready_out <= 1'b1;
end
else begin
case(lookup_state)
IDLE_S: begin
if (key_valid == 1'b1) begin
// ready_out <= 1'b0;
phv_reg <= phv_in;
lookup_state <= WAIT1_S;
end
else begin
phv_out_valid <= 0;
if_match <= 0;
// ready_out <= 1'b1;
lookup_state <= IDLE_S;
end
end
WAIT1_S: begin
if (ready_in) begin
phv_out <= phv_reg;
phv_out_valid <= 1'b1;
if(match == 1'b0) begin // CAM miss
if_match <= 0;
match_addr_out <= 4'hf;
end
else begin // CAM hit
if_match <= 1;
match_addr_out <= match_addr;
end
lookup_state <= IDLE_S;
// ready_out <= 1'b1;
end
else begin
lookup_state <= HALT_S;
end
end
HALT_S: begin
if (ready_in) begin
phv_out <= phv_reg;
phv_out_valid <= 1'b1;
if(match == 1'b0) begin // CAM miss
if_match <= 0;
match_addr_out <= 4'hf;
end
else begin // CAM hit
if_match <= 1;
match_addr_out <= match_addr;
end
lookup_state <= IDLE_S;
// ready_out <= 1'b1;
end
end
endcase
end
end
//======================================================================
//======================================================================
/****control path*****/
wire [7:0] mod_id; //module ID
//4'b0 for tcam entry;
//NOTE: we don't need tcam entry mask
//4'b2 for action table entry;
wire [3:0] resv; //recog between tcam and action
wire [15:0] control_flag; //dst udp port num
reg [7:0] c_index_cam; //table index(addr)
reg c_wr_en_cam; //enable table write(wena)
reg [7:0] c_index_act;
reg c_wr_en_act;
reg [ACT_LEN-1:0] act_entry_tmp;
reg continous_flag;
reg [204:0] cam_entry_reg;
reg [2:0] c_state;
/****for 256b exclusively*****/
reg c_m_axis_tvalid_r;
reg c_m_axis_tlast_r;
localparam IDLE_C = 0,
PARSE_C = 1,
CAM_TMP_ENTRY = 2,
SU_CAM_TMP_ENTRY = 3,
ACT_TMP_ENTRY_WAIT = 4,
ACT_TMP_ENTRY_WAIT_2 = 5,
ACT_TMP_ENTRY = 6,
FLUSH_REST_C = 7;
generate
if(C_S_AXIS_DATA_WIDTH == 512) begin
assign mod_id = c_s_axis_tdata[368+:8];
assign resv = c_s_axis_tdata[376+:4];
assign control_flag = c_s_axis_tdata[335:320];
//LE to BE switching
wire[C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata_swapped;
assign c_s_axis_tdata_swapped = { c_s_axis_tdata[0+:8],
c_s_axis_tdata[8+:8],
c_s_axis_tdata[16+:8],
c_s_axis_tdata[24+:8],
c_s_axis_tdata[32+:8],
c_s_axis_tdata[40+:8],
c_s_axis_tdata[48+:8],
c_s_axis_tdata[56+:8],
c_s_axis_tdata[64+:8],
c_s_axis_tdata[72+:8],
c_s_axis_tdata[80+:8],
c_s_axis_tdata[88+:8],
c_s_axis_tdata[96+:8],
c_s_axis_tdata[104+:8],
c_s_axis_tdata[112+:8],
c_s_axis_tdata[120+:8],
c_s_axis_tdata[128+:8],
c_s_axis_tdata[136+:8],
c_s_axis_tdata[144+:8],
c_s_axis_tdata[152+:8],
c_s_axis_tdata[160+:8],
c_s_axis_tdata[168+:8],
c_s_axis_tdata[176+:8],
c_s_axis_tdata[184+:8],
c_s_axis_tdata[192+:8],
c_s_axis_tdata[200+:8],
c_s_axis_tdata[208+:8],
c_s_axis_tdata[216+:8],
c_s_axis_tdata[224+:8],
c_s_axis_tdata[232+:8],
c_s_axis_tdata[240+:8],
c_s_axis_tdata[248+:8],
c_s_axis_tdata[256+:8],
c_s_axis_tdata[264+:8],
c_s_axis_tdata[272+:8],
c_s_axis_tdata[280+:8],
c_s_axis_tdata[288+:8],
c_s_axis_tdata[296+:8],
c_s_axis_tdata[304+:8],
c_s_axis_tdata[312+:8],
c_s_axis_tdata[320+:8],
c_s_axis_tdata[328+:8],
c_s_axis_tdata[336+:8],
c_s_axis_tdata[344+:8],
c_s_axis_tdata[352+:8],
c_s_axis_tdata[360+:8],
c_s_axis_tdata[368+:8],
c_s_axis_tdata[376+:8],
c_s_axis_tdata[384+:8],
c_s_axis_tdata[392+:8],
c_s_axis_tdata[400+:8],
c_s_axis_tdata[408+:8],
c_s_axis_tdata[416+:8],
c_s_axis_tdata[424+:8],
c_s_axis_tdata[432+:8],
c_s_axis_tdata[440+:8],
c_s_axis_tdata[448+:8],
c_s_axis_tdata[456+:8],
c_s_axis_tdata[464+:8],
c_s_axis_tdata[472+:8],
c_s_axis_tdata[480+:8],
c_s_axis_tdata[488+:8],
c_s_axis_tdata[496+:8],
c_s_axis_tdata[504+:8]
};
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
c_index_cam <= 0;
c_wr_en_cam <= 0;
c_index_act <= 0;
c_wr_en_act <= 0;
act_entry_tmp <= 0;
cam_entry_reg <= 0;
continous_flag <= 0;
c_m_axis_tdata <= 0;
c_m_axis_tuser <= 0;
c_m_axis_tkeep <= 0;
c_m_axis_tvalid <= 0;
c_m_axis_tlast <= 0;
c_state <= IDLE_C;
end
else begin
case(c_state)
IDLE_C: begin
if(c_s_axis_tvalid) begin
if(mod_id[7:3] == STAGE_ID && mod_id[2:0] == LOOKUP_ID
&& control_flag == 16'hf2f1
&& resv == 4'b0) begin // TCAM entry
c_wr_en_cam <= 1'b0;
c_index_cam <= c_s_axis_tdata[384+:8];
c_state <= CAM_TMP_ENTRY;
end
//not for lookup
else begin
c_index_cam <= 0;
c_wr_en_cam <= 0;
c_index_act <= 0;
c_wr_en_act <= 0;
act_entry_tmp <= 0;
continous_flag <= 0;
c_m_axis_tdata <= c_s_axis_tdata;
c_m_axis_tuser <= c_s_axis_tuser;
c_m_axis_tkeep <= c_s_axis_tkeep;
c_m_axis_tvalid <= c_s_axis_tvalid;
c_m_axis_tlast <= c_s_axis_tlast;
c_state <= IDLE_C;
end
end
//stay halt
else begin
c_index_cam <= 0;
c_wr_en_cam <= 0;
c_index_act <= 0;
c_wr_en_act <= 0;
act_entry_tmp <= 0;
continous_flag <= 0;
c_m_axis_tdata <= 0;
c_m_axis_tuser <= 0;
c_m_axis_tkeep <= 0;
c_m_axis_tvalid <= 0;
c_m_axis_tlast <= 0;
c_state <= IDLE_C;
end
end
CAM_TMP_ENTRY: begin
if(c_s_axis_tvalid) begin
cam_entry_reg <= c_s_axis_tdata_swapped[511 -: 205];
c_wr_en_cam <= 1'b1;
if(c_s_axis_tlast) begin
c_state <= IDLE_C;
end
else begin
c_state <= SU_CAM_TMP_ENTRY;
end
end
else begin
c_wr_en_cam <= 1'b0;
end
end
SU_CAM_TMP_ENTRY: begin
if(c_s_axis_tvalid) begin
cam_entry_reg <= c_s_axis_tdata_swapped[511 -: 205];
c_wr_en_cam <= 1'b1;
c_index_cam <= c_index_cam + 1'b1;
if(c_s_axis_tlast) begin
c_state <= IDLE_C;
end
else begin
c_state <= SU_CAM_TMP_ENTRY;
end
end
else begin
c_wr_en_cam <= 1'b0;
end
end
endcase
end
end
if (STAGE_ID == 4) begin
// tcam1 for lookup
cam_top # (
.C_DEPTH (16),
// .C_WIDTH (256),
.C_WIDTH (205),
.C_MEM_INIT (0)
// .C_MEM_INIT_FILE ("./cam_init_file.mif")
)
cam_0
(
.CLK (clk),
.CMP_DIN ({vlan_id[3:0], vlan_id[11:4], extract_key}),
//.CMP_DATA_MASK ({4'b1111, extract_mask}),
.CMP_DATA_MASK (),
.BUSY (),
.MATCH (match),
.MATCH_ADDR (match_addr[3:0]),
//.WE (lookup_din_en),
//.WR_ADDR (lookup_din_addr),
//.DATA_MASK (lookup_din_mask),
//.DIN (lookup_din),
.WE (c_wr_en_cam),
.WR_ADDR (c_index_cam[3:0]),
.DATA_MASK (), //TODO do we need ternary matching?
.DIN (cam_entry_reg),
.EN (1'b1)
);
end
else begin
// tcam1 for lookup
cam_top # (
.C_DEPTH (16),
// .C_WIDTH (256),
.C_WIDTH (205),
.C_MEM_INIT (0)
// .C_MEM_INIT_FILE ("./cam_init_file.mif")
)
cam_0
(
.CLK (clk),
.CMP_DIN ({vlan_id[3:0], vlan_id[11:4], extract_key}),
//.CMP_DATA_MASK ({4'b0000, extract_mask}),
.CMP_DATA_MASK (),
.BUSY (),
.MATCH (match),
.MATCH_ADDR (match_addr[3:0]),
//.WE (lookup_din_en),
//.WR_ADDR (lookup_din_addr),
//.DATA_MASK (lookup_din_mask),
//.DIN (lookup_din),
.WE (c_wr_en_cam),
.WR_ADDR (c_index_cam[3:0]),
.DATA_MASK (), //TODO do we need ternary matching?
.DIN (cam_entry_reg),
.EN (1'b1)
);
end
end
//NOTE: data width is 256b
else begin
wire[C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata_swapped;
assign c_s_axis_tdata_swapped = { c_s_axis_tdata[0+:8],
c_s_axis_tdata[8+:8],
c_s_axis_tdata[16+:8],
c_s_axis_tdata[24+:8],
c_s_axis_tdata[32+:8],
c_s_axis_tdata[40+:8],
c_s_axis_tdata[48+:8],
c_s_axis_tdata[56+:8],
c_s_axis_tdata[64+:8],
c_s_axis_tdata[72+:8],
c_s_axis_tdata[80+:8],
c_s_axis_tdata[88+:8],
c_s_axis_tdata[96+:8],
c_s_axis_tdata[104+:8],
c_s_axis_tdata[112+:8],
c_s_axis_tdata[120+:8],
c_s_axis_tdata[128+:8],
c_s_axis_tdata[136+:8],
c_s_axis_tdata[144+:8],
c_s_axis_tdata[152+:8],
c_s_axis_tdata[160+:8],
c_s_axis_tdata[168+:8],
c_s_axis_tdata[176+:8],
c_s_axis_tdata[184+:8],
c_s_axis_tdata[192+:8],
c_s_axis_tdata[200+:8],
c_s_axis_tdata[208+:8],
c_s_axis_tdata[216+:8],
c_s_axis_tdata[224+:8],
c_s_axis_tdata[232+:8],
c_s_axis_tdata[240+:8],
c_s_axis_tdata[248+:8]};
assign mod_id = c_s_axis_tdata[112+:8];
assign resv = c_s_axis_tdata[120+:4];
assign control_flag = c_s_axis_tdata[64+:16];
//
reg [2:0] c_state_next;
reg [C_S_AXIS_DATA_WIDTH-1:0] r_tdata, c_s_axis_tdata_d1;
reg [C_S_AXIS_TUSER_WIDTH-1:0] r_tuser, c_s_axis_tuser_d1;
reg [C_S_AXIS_DATA_WIDTH/8-1:0] r_tkeep, c_s_axis_tkeep_d1;
reg r_tlast, c_s_axis_tlast_d1;
reg r_tvalid, c_s_axis_tvalid_d1;
reg [C_S_AXIS_DATA_WIDTH-1:0] r_1st_tdata, r_1st_tdata_next;
reg [C_S_AXIS_TUSER_WIDTH-1:0] r_1st_tuser, r_1st_tuser_next;
reg [C_S_AXIS_DATA_WIDTH/8-1:0] r_1st_tkeep, r_1st_tkeep_next;
reg r_1st_tlast, r_1st_tlast_next;
reg r_1st_tvalid, r_1st_tvalid_next;
reg [7:0] c_index_cam_next, c_index_act_next;
reg c_wr_en_cam_next, c_wr_en_act_next;
reg [204:0] c_wr_cam_data, c_wr_cam_data_next;
reg [ACT_LEN-1:0] c_wr_act_data, c_wr_act_data_next;
always @(*) begin
c_state_next = c_state;
r_tdata = 0;
r_tkeep = 0;
r_tuser = 0;
r_tlast = 0;
r_tvalid = 0;
r_1st_tdata_next = r_1st_tdata;
r_1st_tkeep_next = r_1st_tkeep;
r_1st_tuser_next = r_1st_tuser;
r_1st_tlast_next = r_1st_tlast;
r_1st_tvalid_next = r_1st_tvalid;
c_index_cam_next = c_index_cam;
c_index_act_next = c_index_act;
c_wr_en_cam_next = 0;
c_wr_en_act_next = 0;
c_wr_cam_data_next = c_wr_cam_data;
c_wr_act_data_next = c_wr_act_data;
case (c_state)
IDLE_C: begin // 1st segment
r_tvalid = 0;
if (c_s_axis_tvalid) begin
// store 1st segment
r_1st_tdata_next = c_s_axis_tdata;
r_1st_tuser_next = c_s_axis_tuser;
r_1st_tkeep_next = c_s_axis_tkeep;
r_1st_tlast_next = c_s_axis_tlast;
r_1st_tvalid_next = c_s_axis_tvalid;
c_state_next = PARSE_C;
end
end
PARSE_C: begin // 2nd segment
if (mod_id[7:3] == STAGE_ID && mod_id[2:0] == LOOKUP_ID &&
control_flag == 16'hf2f1 && c_s_axis_tvalid && resv==4'b0) begin
// should not emit segment
c_index_cam_next = c_s_axis_tdata[128+:8];
c_state_next = CAM_TMP_ENTRY;
end
else if (!c_s_axis_tvalid) begin
end
else begin
// emit
r_tdata = r_1st_tdata;
r_tkeep = r_1st_tkeep;
r_tuser = r_1st_tuser;
r_tlast = r_1st_tlast;
r_tvalid = r_1st_tvalid;
c_state_next = FLUSH_REST_C;
end
end
CAM_TMP_ENTRY: begin
if (c_s_axis_tvalid) begin
c_wr_en_cam_next = 1; // next clk to write
c_wr_cam_data_next = c_s_axis_tdata_swapped[51+:205];
c_state_next = IDLE_C;
end
end
FLUSH_REST_C: begin
c_wr_en_cam_next = 0;
c_wr_en_act_next = 0;
r_tdata = c_s_axis_tdata_d1;
r_tkeep = c_s_axis_tkeep_d1;
r_tuser = c_s_axis_tuser_d1;
r_tlast = c_s_axis_tlast_d1;
r_tvalid = c_s_axis_tvalid_d1;
if (c_s_axis_tvalid_d1 && c_s_axis_tlast_d1) begin
c_state_next = IDLE_C;
end
end
endcase
end
always @(posedge clk) begin
if (~rst_n) begin
c_state <= IDLE_C;
// control output
c_m_axis_tdata <= 0;
c_m_axis_tuser <= 0;
c_m_axis_tkeep <= 0;
c_m_axis_tlast <= 0;
c_m_axis_tvalid <= 0;
//
c_index_cam <= 0;
c_index_act <= 0;
c_wr_en_cam <= 0;
c_wr_en_act <= 0;
c_wr_cam_data <= 0;
c_wr_act_data <= 0;
end
else begin
c_state <= c_state_next;
// output ctrl master signals
c_m_axis_tdata <= r_tdata;
c_m_axis_tkeep <= r_tkeep;
c_m_axis_tuser <= r_tuser;
c_m_axis_tlast <= r_tlast;
c_m_axis_tvalid <= r_tvalid;
//
c_index_cam <= c_index_cam_next;
c_index_act <= c_index_act_next;
c_wr_en_cam <= c_wr_en_cam_next;
c_wr_en_act <= c_wr_en_act_next;
c_wr_cam_data <= c_wr_cam_data_next;
c_wr_act_data <= c_wr_act_data_next;
end
end
always @(posedge clk) begin
if (~rst_n) begin
// delayed 1 clk
c_s_axis_tdata_d1 <= 0;
c_s_axis_tuser_d1 <= 0;
c_s_axis_tkeep_d1 <= 0;
c_s_axis_tlast_d1 <= 0;
c_s_axis_tvalid_d1 <= 0;
//
r_1st_tdata <= 0;
r_1st_tkeep <= 0;
r_1st_tuser <= 0;
r_1st_tlast <= 0;
r_1st_tvalid <= 0;
end
else begin
// delayed 1 clk
c_s_axis_tdata_d1 <= c_s_axis_tdata;
c_s_axis_tuser_d1 <= c_s_axis_tuser;
c_s_axis_tkeep_d1 <= c_s_axis_tkeep;
c_s_axis_tlast_d1 <= c_s_axis_tlast;
c_s_axis_tvalid_d1 <= c_s_axis_tvalid;
//
r_1st_tdata <= r_1st_tdata_next;
r_1st_tkeep <= r_1st_tkeep_next;
r_1st_tuser <= r_1st_tuser_next;
r_1st_tlast <= r_1st_tlast_next;
r_1st_tvalid <= r_1st_tvalid_next;
end
end
if (STAGE_ID == 4) begin
// tcam1 for lookup
cam_top # (
.C_DEPTH (16),
// .C_WIDTH (256),
.C_WIDTH (205), // 192+1+12
.C_MEM_INIT (0)
// .C_MEM_INIT_FILE ("./cam_init_file.mif")
)
//TODO remember to change it back.
cam_0
(
.CLK (clk),
.RST (~rst_n),
.CMP_DIN ({vlan_id[3:0], vlan_id[11:4], extract_key}),
// .CMP_DATA_MASK ({4'b1111, extract_mask}),
.CMP_DATA_MASK (),
.BUSY (),
.MATCH (match),
.MATCH_ADDR (match_addr),
//.WE (lookup_din_en),
//.WR_ADDR (lookup_din_addr),
//.DATA_MASK (lookup_din_mask),
//.DIN (lookup_din),
.WE (c_wr_en_cam),
.WR_ADDR (c_index_cam[3:0]),
// .WR_ADDR (c_index_cam),
.DATA_MASK (), //TODO do we need ternary matching?
.DIN (c_wr_cam_data),
.EN (1'b1)
);
end
else begin
// tcam1 for lookup
cam_top # (
.C_DEPTH (16),
// .C_WIDTH (256),
.C_WIDTH (205), // 192+1+12
.C_MEM_INIT (0)
// .C_MEM_INIT_FILE ("./cam_init_file.mif")
)
//TODO remember to change it back.
cam_0
(
.CLK (clk),
.RST (~rst_n),
.CMP_DIN ({vlan_id[3:0], vlan_id[11:4], extract_key}),
// .CMP_DATA_MASK ({4'b0000, extract_mask}),
.CMP_DATA_MASK (),
.BUSY (),
.MATCH (match),
.MATCH_ADDR (match_addr),
//.WE (lookup_din_en),
//.WR_ADDR (lookup_din_addr),
//.DATA_MASK (lookup_din_mask),
//.DIN (lookup_din),
.WE (c_wr_en_cam),
.WR_ADDR (c_index_cam[3:0]),
// .WR_ADDR (c_index_cam),
.DATA_MASK (), //TODO do we need ternary matching?
.DIN (c_wr_cam_data),
.EN (1'b1)
);
end
end
endgenerate
endmodule
`timescale 1ns / 1ps
module lke_ram_part #(
parameter C_S_AXIS_DATA_WIDTH = 512,
parameter C_S_AXIS_TUSER_WIDTH = 128,
parameter STAGE_ID = 0,
parameter PHV_LEN = 48*8+32*8+16*8+256,
parameter KEY_LEN = 48*2+32*2+16*2+5,
parameter ACT_LEN = 625,
parameter LOOKUP_ID = 2,
parameter C_VLANID_WIDTH = 12
)
(
input clk,
input rst_n,
//output from key extractor
input [PHV_LEN-1:0] phv_in,
input phv_valid,
input [3:0] match_addr,
input if_match,
output ready_out,
//output to the action engine
output [ACT_LEN-1:0] action,
output reg action_valid,
output reg [PHV_LEN-1:0] phv_out,
input ready_in,
// output vlan to the action engine
output reg [C_VLANID_WIDTH-1:0] act_vlan_out,
output reg act_vlan_out_valid,
input act_vlan_ready,
//control path
input [C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata,
input [C_S_AXIS_TUSER_WIDTH-1:0] c_s_axis_tuser,
input [C_S_AXIS_DATA_WIDTH/8-1:0] c_s_axis_tkeep,
input c_s_axis_tvalid,
input c_s_axis_tlast,
output reg [C_S_AXIS_DATA_WIDTH-1:0] c_m_axis_tdata,
output reg [C_S_AXIS_TUSER_WIDTH-1:0] c_m_axis_tuser,
output reg [C_S_AXIS_DATA_WIDTH/8-1:0] c_m_axis_tkeep,
output reg c_m_axis_tvalid,
output reg c_m_axis_tlast
);
/********intermediate variables declared here********/
wire [ACT_LEN-1:0] action_wire;
wire [11:0] vlan_id;
assign vlan_id = phv_in[140:129];
reg [PHV_LEN-1:0] phv_reg;
reg if_match_d1;
reg [2:0] lookup_state;
assign action = (if_match_d1==1)?action_wire:625'h3f;
//here, the output should be controlled.
localparam IDLE_S = 3'd0,
WAIT1_S = 3'd1,
WAIT2_S = 3'd2,
TRANS_S = 3'd3,
HALT_S = 3'd4,
EMPTY1_S = 3'd5,
OUTPUT_S = 3'd6;
assign ready_out = lookup_state!=HALT_S;
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
phv_reg <= 0;
action_valid <= 1'b0;
lookup_state <= IDLE_S;
phv_out <= 0;
// ready_out <= 1'b1;
act_vlan_out <= 0;
act_vlan_out_valid <= 0;
if_match_d1 <= 0;
end
else begin
case(lookup_state)
IDLE_S: begin
if (phv_valid == 1'b1) begin
// ready_out <= 1'b0;
phv_reg <= phv_in;
act_vlan_out <= vlan_id;
if_match_d1 <= if_match;
if (act_vlan_ready) begin
act_vlan_out_valid <= 1;
end
lookup_state <= WAIT1_S;
end
else begin
// ready_out <= 1'b1;
lookup_state <= IDLE_S;
action_valid <= 1'b0;
act_vlan_out_valid <= 0;
if_match_d1 <= 0;
end
end
WAIT1_S: begin
if (ready_in) begin
act_vlan_out_valid <= 0;
action_valid <= 1'b1;
// ready_out <= 1'b1;
phv_out <= phv_reg;
lookup_state <= IDLE_S;
end
else begin
lookup_state <= HALT_S;
end
end
HALT_S: begin
if (ready_in) begin
act_vlan_out_valid <= 0;
action_valid <= 1'b1;
// ready_out <= 1'b1;
phv_out <= phv_reg;
lookup_state <= IDLE_S;
end
end
endcase
end
end
//======================================================================
//======================================================================
/****control path*****/
wire [7:0] mod_id; //module ID
//4'b0 for tcam entry;
//NOTE: we don't need tcam entry mask
//4'b2 for action table entry;
wire [3:0] resv; //recog between tcam and action
wire [15:0] control_flag; //dst udp port num
reg [7:0] c_index_cam; //table index(addr)
reg c_wr_en_cam; //enable table write(wena)
reg [7:0] c_index_act;
reg c_wr_en_act;
reg [ACT_LEN-1:0] act_entry_tmp;
reg continous_flag;
reg [204:0] cam_entry_reg;
reg [2:0] c_state;
/****for 256b exclusively*****/
reg c_m_axis_tvalid_r;
reg c_m_axis_tlast_r;
localparam IDLE_C = 0,
PARSE_C = 1,
CAM_TMP_ENTRY = 2,
SU_CAM_TMP_ENTRY = 3,
ACT_TMP_ENTRY_WAIT = 4,
ACT_TMP_ENTRY_WAIT_2 = 5,
ACT_TMP_ENTRY = 6,
FLUSH_REST_C = 7;
generate
if(C_S_AXIS_DATA_WIDTH == 512) begin
assign mod_id = c_s_axis_tdata[368+:8];
assign resv = c_s_axis_tdata[376+:4];
assign control_flag = c_s_axis_tdata[335:320];
//LE to BE switching
wire[C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata_swapped;
assign c_s_axis_tdata_swapped = { c_s_axis_tdata[0+:8],
c_s_axis_tdata[8+:8],
c_s_axis_tdata[16+:8],
c_s_axis_tdata[24+:8],
c_s_axis_tdata[32+:8],
c_s_axis_tdata[40+:8],
c_s_axis_tdata[48+:8],
c_s_axis_tdata[56+:8],
c_s_axis_tdata[64+:8],
c_s_axis_tdata[72+:8],
c_s_axis_tdata[80+:8],
c_s_axis_tdata[88+:8],
c_s_axis_tdata[96+:8],
c_s_axis_tdata[104+:8],
c_s_axis_tdata[112+:8],
c_s_axis_tdata[120+:8],
c_s_axis_tdata[128+:8],
c_s_axis_tdata[136+:8],
c_s_axis_tdata[144+:8],
c_s_axis_tdata[152+:8],
c_s_axis_tdata[160+:8],
c_s_axis_tdata[168+:8],
c_s_axis_tdata[176+:8],
c_s_axis_tdata[184+:8],
c_s_axis_tdata[192+:8],
c_s_axis_tdata[200+:8],
c_s_axis_tdata[208+:8],
c_s_axis_tdata[216+:8],
c_s_axis_tdata[224+:8],
c_s_axis_tdata[232+:8],
c_s_axis_tdata[240+:8],
c_s_axis_tdata[248+:8],
c_s_axis_tdata[256+:8],
c_s_axis_tdata[264+:8],
c_s_axis_tdata[272+:8],
c_s_axis_tdata[280+:8],
c_s_axis_tdata[288+:8],
c_s_axis_tdata[296+:8],
c_s_axis_tdata[304+:8],
c_s_axis_tdata[312+:8],
c_s_axis_tdata[320+:8],
c_s_axis_tdata[328+:8],
c_s_axis_tdata[336+:8],
c_s_axis_tdata[344+:8],
c_s_axis_tdata[352+:8],
c_s_axis_tdata[360+:8],
c_s_axis_tdata[368+:8],
c_s_axis_tdata[376+:8],
c_s_axis_tdata[384+:8],
c_s_axis_tdata[392+:8],
c_s_axis_tdata[400+:8],
c_s_axis_tdata[408+:8],
c_s_axis_tdata[416+:8],
c_s_axis_tdata[424+:8],
c_s_axis_tdata[432+:8],
c_s_axis_tdata[440+:8],
c_s_axis_tdata[448+:8],
c_s_axis_tdata[456+:8],
c_s_axis_tdata[464+:8],
c_s_axis_tdata[472+:8],
c_s_axis_tdata[480+:8],
c_s_axis_tdata[488+:8],
c_s_axis_tdata[496+:8],
c_s_axis_tdata[504+:8]
};
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
c_index_cam <= 0;
c_wr_en_cam <= 0;
c_index_act <= 0;
c_wr_en_act <= 0;
act_entry_tmp <= 0;
cam_entry_reg <= 0;
continous_flag <= 0;
c_m_axis_tdata <= 0;
c_m_axis_tuser <= 0;
c_m_axis_tkeep <= 0;
c_m_axis_tvalid <= 0;
c_m_axis_tlast <= 0;
c_state <= IDLE_C;
end
else begin
case(c_state)
IDLE_C: begin
if(c_s_axis_tvalid) begin
if(mod_id[7:3] == STAGE_ID && mod_id[2:0] == LOOKUP_ID
&& control_flag == 16'hf2f1
&& resv != 4'b0) begin
//ACTION entry
continous_flag <= 1'b0;
c_index_act <= c_s_axis_tdata[384+:8];
c_state <= ACT_TMP_ENTRY_WAIT;
end
//not for lookup
else begin
c_index_cam <= 0;
c_wr_en_cam <= 0;
c_index_act <= 0;
c_wr_en_act <= 0;
act_entry_tmp <= 0;
continous_flag <= 0;
c_m_axis_tdata <= c_s_axis_tdata;
c_m_axis_tuser <= c_s_axis_tuser;
c_m_axis_tkeep <= c_s_axis_tkeep;
c_m_axis_tvalid <= c_s_axis_tvalid;
c_m_axis_tlast <= c_s_axis_tlast;
c_state <= IDLE_C;
end
end
//stay halt
else begin
c_index_cam <= 0;
c_wr_en_cam <= 0;
c_index_act <= 0;
c_wr_en_act <= 0;
act_entry_tmp <= 0;
continous_flag <= 0;
c_m_axis_tdata <= 0;
c_m_axis_tuser <= 0;
c_m_axis_tkeep <= 0;
c_m_axis_tvalid <= 0;
c_m_axis_tlast <= 0;
c_state <= IDLE_C;
end
end
ACT_TMP_ENTRY_WAIT: begin
c_m_axis_tvalid_r <= 1'b0;
c_m_axis_tlast_r <= 1'b0;
//flush the whole table
if(c_s_axis_tvalid && ~c_s_axis_tlast) begin
if (continous_flag) c_index_act <= c_index_act + 8'b1;
else c_index_act <= c_index_act;
act_entry_tmp[624 -: 512] <= c_s_axis_tdata_swapped;
c_wr_en_act <= 1'b0;
c_state <= ACT_TMP_ENTRY;
end
else if(c_s_axis_tvalid && c_s_axis_tlast) begin
c_wr_en_act <= 1'b0;
c_state <= IDLE_C;
end
else begin
c_wr_en_act <= 1'b0;
c_state <= c_state;
end
end
ACT_TMP_ENTRY: begin
if(c_s_axis_tvalid) begin
act_entry_tmp[112:0] <= c_s_axis_tdata_swapped[511-:113];
c_wr_en_act <= 1'b1;
if(c_s_axis_tlast) c_state <= IDLE_C;
else begin
continous_flag <= 1'b1;
c_state <= ACT_TMP_ENTRY_WAIT;
end
end
else begin
c_state <= c_state;
act_entry_tmp <= act_entry_tmp;
c_wr_en_act <= c_wr_en_act;
end
end
endcase
end
end
//ram for action
// blk_mem_gen_1 #(
// .C_INIT_FILE_NAME ("./llup.mif"),
// .C_LOAD_INIT_FILE (1)
// )
blk_mem_gen_1
act_ram_625w_16d
(
.addra(c_index_act[3:0]),
.clka(clk),
.dina(act_entry_tmp),
.ena(1'b1),
.wea(c_wr_en_act),
.addrb(match_addr[3:0]),
.clkb(clk),
.doutb(action_wire),
.enb(1'b1)
);
end
//NOTE: data width is 256b
else begin
wire[C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata_swapped;
assign c_s_axis_tdata_swapped = { c_s_axis_tdata[0+:8],
c_s_axis_tdata[8+:8],
c_s_axis_tdata[16+:8],
c_s_axis_tdata[24+:8],
c_s_axis_tdata[32+:8],
c_s_axis_tdata[40+:8],
c_s_axis_tdata[48+:8],
c_s_axis_tdata[56+:8],
c_s_axis_tdata[64+:8],
c_s_axis_tdata[72+:8],
c_s_axis_tdata[80+:8],
c_s_axis_tdata[88+:8],
c_s_axis_tdata[96+:8],
c_s_axis_tdata[104+:8],
c_s_axis_tdata[112+:8],
c_s_axis_tdata[120+:8],
c_s_axis_tdata[128+:8],
c_s_axis_tdata[136+:8],
c_s_axis_tdata[144+:8],
c_s_axis_tdata[152+:8],
c_s_axis_tdata[160+:8],
c_s_axis_tdata[168+:8],
c_s_axis_tdata[176+:8],
c_s_axis_tdata[184+:8],
c_s_axis_tdata[192+:8],
c_s_axis_tdata[200+:8],
c_s_axis_tdata[208+:8],
c_s_axis_tdata[216+:8],
c_s_axis_tdata[224+:8],
c_s_axis_tdata[232+:8],
c_s_axis_tdata[240+:8],
c_s_axis_tdata[248+:8]};
assign mod_id = c_s_axis_tdata[112+:8];
assign resv = c_s_axis_tdata[120+:4];
assign control_flag = c_s_axis_tdata[64+:16];
//
reg [2:0] c_state_next;
reg [C_S_AXIS_DATA_WIDTH-1:0] r_tdata, c_s_axis_tdata_d1;
reg [C_S_AXIS_TUSER_WIDTH-1:0] r_tuser, c_s_axis_tuser_d1;
reg [C_S_AXIS_DATA_WIDTH/8-1:0] r_tkeep, c_s_axis_tkeep_d1;
reg r_tlast, c_s_axis_tlast_d1;
reg r_tvalid, c_s_axis_tvalid_d1;
reg [C_S_AXIS_DATA_WIDTH-1:0] r_1st_tdata, r_1st_tdata_next;
reg [C_S_AXIS_TUSER_WIDTH-1:0] r_1st_tuser, r_1st_tuser_next;
reg [C_S_AXIS_DATA_WIDTH/8-1:0] r_1st_tkeep, r_1st_tkeep_next;
reg r_1st_tlast, r_1st_tlast_next;
reg r_1st_tvalid, r_1st_tvalid_next;
reg [7:0] c_index_cam_next, c_index_act_next;
reg c_wr_en_cam_next, c_wr_en_act_next;
reg [204:0] c_wr_cam_data, c_wr_cam_data_next;
reg [ACT_LEN-1:0] c_wr_act_data, c_wr_act_data_next;
always @(*) begin
c_state_next = c_state;
r_tdata = 0;
r_tkeep = 0;
r_tuser = 0;
r_tlast = 0;
r_tvalid = 0;
r_1st_tdata_next = r_1st_tdata;
r_1st_tkeep_next = r_1st_tkeep;
r_1st_tuser_next = r_1st_tuser;
r_1st_tlast_next = r_1st_tlast;
r_1st_tvalid_next = r_1st_tvalid;
c_index_cam_next = c_index_cam;
c_index_act_next = c_index_act;
c_wr_en_cam_next = 0;
c_wr_en_act_next = 0;
c_wr_cam_data_next = c_wr_cam_data;
c_wr_act_data_next = c_wr_act_data;
case (c_state)
IDLE_C: begin // 1st segment
r_tvalid = 0;
if (c_s_axis_tvalid) begin
// store 1st segment
r_1st_tdata_next = c_s_axis_tdata;
r_1st_tuser_next = c_s_axis_tuser;
r_1st_tkeep_next = c_s_axis_tkeep;
r_1st_tlast_next = c_s_axis_tlast;
r_1st_tvalid_next = c_s_axis_tvalid;
c_state_next = PARSE_C;
end
end
PARSE_C: begin // 2nd segment
if (mod_id[7:3] == STAGE_ID && mod_id[2:0] == LOOKUP_ID &&
control_flag == 16'hf2f1 && c_s_axis_tvalid && resv!=4'b0) begin
// should not emit segment
c_index_act_next = c_s_axis_tdata[128+:8];
c_state_next = ACT_TMP_ENTRY_WAIT;
end
else if (!c_s_axis_tvalid) begin
end
else begin
// emit
r_tdata = r_1st_tdata;
r_tkeep = r_1st_tkeep;
r_tuser = r_1st_tuser;
r_tlast = r_1st_tlast;
r_tvalid = r_1st_tvalid;
c_state_next = FLUSH_REST_C;
end
end
ACT_TMP_ENTRY_WAIT: begin
if (c_s_axis_tvalid) begin
c_wr_act_data_next[369+:256] = c_s_axis_tdata_swapped;
c_state_next = ACT_TMP_ENTRY_WAIT_2;
end
end
ACT_TMP_ENTRY_WAIT_2: begin
if (c_s_axis_tvalid) begin
c_wr_act_data_next[113+:256] = c_s_axis_tdata_swapped;
c_state_next = ACT_TMP_ENTRY;
end
end
ACT_TMP_ENTRY: begin
if (c_s_axis_tvalid) begin
c_wr_en_act_next = 1; // next clk to write
c_wr_act_data_next[0+:113] = c_s_axis_tdata_swapped[143+:113];
c_state_next = IDLE_C;
end
end
FLUSH_REST_C: begin
c_wr_en_cam_next = 0;
c_wr_en_act_next = 0;
r_tdata = c_s_axis_tdata_d1;
r_tkeep = c_s_axis_tkeep_d1;
r_tuser = c_s_axis_tuser_d1;
r_tlast = c_s_axis_tlast_d1;
r_tvalid = c_s_axis_tvalid_d1;
if (c_s_axis_tvalid_d1 && c_s_axis_tlast_d1) begin
c_state_next = IDLE_C;
end
end
endcase
end
always @(posedge clk) begin
if (~rst_n) begin
c_state <= IDLE_C;
// control output
c_m_axis_tdata <= 0;
c_m_axis_tuser <= 0;
c_m_axis_tkeep <= 0;
c_m_axis_tlast <= 0;
c_m_axis_tvalid <= 0;
//
c_index_cam <= 0;
c_index_act <= 0;
c_wr_en_cam <= 0;
c_wr_en_act <= 0;
c_wr_cam_data <= 0;
c_wr_act_data <= 0;
end
else begin
c_state <= c_state_next;
// output ctrl master signals
c_m_axis_tdata <= r_tdata;
c_m_axis_tkeep <= r_tkeep;
c_m_axis_tuser <= r_tuser;
c_m_axis_tlast <= r_tlast;
c_m_axis_tvalid <= r_tvalid;
//
c_index_cam <= c_index_cam_next;
c_index_act <= c_index_act_next;
c_wr_en_cam <= c_wr_en_cam_next;
c_wr_en_act <= c_wr_en_act_next;
c_wr_cam_data <= c_wr_cam_data_next;
c_wr_act_data <= c_wr_act_data_next;
end
end
always @(posedge clk) begin
if (~rst_n) begin
// delayed 1 clk
c_s_axis_tdata_d1 <= 0;
c_s_axis_tuser_d1 <= 0;
c_s_axis_tkeep_d1 <= 0;
c_s_axis_tlast_d1 <= 0;
c_s_axis_tvalid_d1 <= 0;
//
r_1st_tdata <= 0;
r_1st_tkeep <= 0;
r_1st_tuser <= 0;
r_1st_tlast <= 0;
r_1st_tvalid <= 0;
end
else begin
// delayed 1 clk
c_s_axis_tdata_d1 <= c_s_axis_tdata;
c_s_axis_tuser_d1 <= c_s_axis_tuser;
c_s_axis_tkeep_d1 <= c_s_axis_tkeep;
c_s_axis_tlast_d1 <= c_s_axis_tlast;
c_s_axis_tvalid_d1 <= c_s_axis_tvalid;
//
r_1st_tdata <= r_1st_tdata_next;
r_1st_tkeep <= r_1st_tkeep_next;
r_1st_tuser <= r_1st_tuser_next;
r_1st_tlast <= r_1st_tlast_next;
r_1st_tvalid <= r_1st_tvalid_next;
end
end
//ram for action
// blk_mem_gen_1 #(
// .C_INIT_FILE_NAME ("./llup.mif"),
// .C_LOAD_INIT_FILE (1)
// )
blk_mem_gen_1
act_ram_625w_16d
(
.addra(c_index_act[3:0]),
.clka(clk),
.dina(c_wr_act_data),
.ena(1'b1), // always set to 1
.wea(c_wr_en_act),
.addrb(match_addr),
.clkb(clk),
.doutb(action_wire),
.enb(1'b1) // always set to 1
);
end
endgenerate
endmodule
`timescale 1ns / 1ps
module lookup_engine_top #(
parameter C_S_AXIS_DATA_WIDTH = 512,
parameter C_S_AXIS_TUSER_WIDTH = 128,
parameter STAGE_ID = 0,
parameter PHV_LEN = 48*8+32*8+16*8+256,
parameter KEY_LEN = 48*2+32*2+16*2+5,
parameter ACT_LEN = 625,
parameter LOOKUP_ID = 2,
parameter C_VLANID_WIDTH = 12
)
(
input clk,
input rst_n,
//output from key extractor
input [KEY_LEN-1:0] extract_key,
input key_valid,
input phv_valid,
input [PHV_LEN-1:0] phv_in,
output ready_out,
//output to the action engine
output [ACT_LEN-1:0] action,
output action_valid,
output [PHV_LEN-1:0] phv_out,
input ready_in,
// output vlan to ALU vlan fifo
output [C_VLANID_WIDTH-1:0] act_vlan_out,
output act_vlan_valid_out,
input act_vlan_ready,
//control path
input [C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata,
input [C_S_AXIS_TUSER_WIDTH-1:0] c_s_axis_tuser,
input [C_S_AXIS_DATA_WIDTH/8-1:0] c_s_axis_tkeep,
input c_s_axis_tvalid,
input c_s_axis_tlast,
output [C_S_AXIS_DATA_WIDTH-1:0] c_m_axis_tdata,
output [C_S_AXIS_TUSER_WIDTH-1:0] c_m_axis_tuser,
output [C_S_AXIS_DATA_WIDTH/8-1:0] c_m_axis_tkeep,
output c_m_axis_tvalid,
output c_m_axis_tlast
);
wire [C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata_0;
wire [C_S_AXIS_TUSER_WIDTH-1:0] c_s_axis_tuser_0;
wire [C_S_AXIS_DATA_WIDTH/8-1:0] c_s_axis_tkeep_0;
wire c_s_axis_tvalid_0;
wire c_s_axis_tlast_0;
wire [PHV_LEN-1:0] cam_phv_out;
wire cam_phv_out_valid;
wire [3:0] cam_match_addr_out;
wire cam_if_match;
wire lke_ram_ready;
reg [PHV_LEN-1:0] cam_phv_out_d1;
reg cam_phv_out_valid_d1;
reg [3:0] cam_match_addr_out_d1;
reg cam_if_match_d1;
always @(posedge clk) begin
if (~rst_n) begin
cam_phv_out_d1 <= 0;
cam_phv_out_valid_d1 <= 0;
cam_match_addr_out_d1 <= 0;
cam_if_match_d1 <= 0;
end
else begin
cam_phv_out_d1 <= cam_phv_out;
cam_phv_out_valid_d1 <= cam_phv_out_valid;
cam_match_addr_out_d1 <= cam_match_addr_out;
cam_if_match_d1 <= cam_if_match;
end
end
lke_cam_part #(
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.C_S_AXIS_TUSER_WIDTH(C_S_AXIS_TUSER_WIDTH),
.STAGE_ID(STAGE_ID),
.PHV_LEN(PHV_LEN),
.KEY_LEN(KEY_LEN),
.ACT_LEN(ACT_LEN),
.LOOKUP_ID(LOOKUP_ID),
.C_VLANID_WIDTH(C_VLANID_WIDTH)
)
lke_cam (
.clk (clk),
.rst_n (rst_n),
.extract_key (extract_key),
.key_valid (key_valid),
.phv_valid (phv_valid),
.phv_in (phv_in),
.ready_out (ready_out),
//
.phv_out (cam_phv_out),
.phv_out_valid (cam_phv_out_valid),
.match_addr_out (cam_match_addr_out),
.if_match (cam_if_match),
.ready_in (lke_ram_ready),
//
.c_s_axis_tdata (c_s_axis_tdata),
.c_s_axis_tuser (c_s_axis_tuser),
.c_s_axis_tkeep (c_s_axis_tkeep),
.c_s_axis_tvalid (c_s_axis_tvalid),
.c_s_axis_tlast (c_s_axis_tlast),
.c_m_axis_tdata (c_s_axis_tdata_0),
.c_m_axis_tuser (c_s_axis_tuser_0),
.c_m_axis_tkeep (c_s_axis_tkeep_0),
.c_m_axis_tvalid (c_s_axis_tvalid_0),
.c_m_axis_tlast (c_s_axis_tlast_0)
);
lke_ram_part #(
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.C_S_AXIS_TUSER_WIDTH(C_S_AXIS_TUSER_WIDTH),
.STAGE_ID(STAGE_ID),
.PHV_LEN(PHV_LEN),
.KEY_LEN(KEY_LEN),
.ACT_LEN(ACT_LEN),
.LOOKUP_ID(LOOKUP_ID),
.C_VLANID_WIDTH(C_VLANID_WIDTH)
)
lke_ram (
.clk (clk),
.rst_n (rst_n),
.phv_in (cam_phv_out_d1),
.phv_valid (cam_phv_out_valid_d1),
.match_addr (cam_match_addr_out_d1),
.if_match (cam_if_match_d1),
.ready_out (lke_ram_ready),
//
.action (action),
.action_valid (action_valid),
.phv_out (phv_out),
.ready_in (ready_in),
//
.act_vlan_out (act_vlan_out),
.act_vlan_out_valid (act_vlan_valid_out),
.act_vlan_ready (act_vlan_ready),
.c_s_axis_tdata (c_s_axis_tdata_0),
.c_s_axis_tuser (c_s_axis_tuser_0),
.c_s_axis_tkeep (c_s_axis_tkeep_0),
.c_s_axis_tvalid (c_s_axis_tvalid_0),
.c_s_axis_tlast (c_s_axis_tlast_0),
.c_m_axis_tdata (c_m_axis_tdata),
.c_m_axis_tuser (c_m_axis_tuser),
.c_m_axis_tkeep (c_m_axis_tkeep),
.c_m_axis_tvalid (c_m_axis_tvalid),
.c_m_axis_tlast (c_m_axis_tlast)
);
endmodule
`timescale 1ns / 1ps
module output_arbiter #(
parameter C_AXIS_DATA_WIDTH=256,
parameter C_AXIS_TUSER_WIDTH=128,
parameter C_NUM_QUEUES=4,
parameter C_NUM_QUEUES_WIDTH=2
)
(
input axis_clk,
input aresetn,
// output
output [C_AXIS_DATA_WIDTH-1:0] m_axis_tdata,
output [C_AXIS_DATA_WIDTH/8-1:0] m_axis_tkeep,
output [C_AXIS_TUSER_WIDTH-1:0] m_axis_tuser,
output m_axis_tvalid,
output m_axis_tlast,
input m_axis_tready,
// input
input [C_AXIS_DATA_WIDTH-1:0] s_axis_tdata_0,
input [C_AXIS_DATA_WIDTH/8-1:0] s_axis_tkeep_0,
input [C_AXIS_TUSER_WIDTH-1:0] s_axis_tuser_0,
input s_axis_tlast_0,
input s_axis_tvalid_0,
output s_axis_tready_0,
input [C_AXIS_DATA_WIDTH-1:0] s_axis_tdata_1,
input [C_AXIS_DATA_WIDTH/8-1:0] s_axis_tkeep_1,
input [C_AXIS_TUSER_WIDTH-1:0] s_axis_tuser_1,
input s_axis_tlast_1,
input s_axis_tvalid_1,
output s_axis_tready_1,
input [C_AXIS_DATA_WIDTH-1:0] s_axis_tdata_2,
input [C_AXIS_DATA_WIDTH/8-1:0] s_axis_tkeep_2,
input [C_AXIS_TUSER_WIDTH-1:0] s_axis_tuser_2,
input s_axis_tlast_2,
input s_axis_tvalid_2,
output s_axis_tready_2,
input [C_AXIS_DATA_WIDTH-1:0] s_axis_tdata_3,
input [C_AXIS_DATA_WIDTH/8-1:0] s_axis_tkeep_3,
input [C_AXIS_TUSER_WIDTH-1:0] s_axis_tuser_3,
input s_axis_tlast_3,
input s_axis_tvalid_3,
output s_axis_tready_3
);
wire [C_NUM_QUEUES-1:0] nearly_full;
wire [C_NUM_QUEUES-1:0] empty;
wire [C_AXIS_DATA_WIDTH-1:0] in_tdata [C_NUM_QUEUES-1:0];
wire [C_AXIS_DATA_WIDTH/8-1:0] in_tkeep [C_NUM_QUEUES-1:0];
wire [C_AXIS_TUSER_WIDTH-1:0] in_tuser [C_NUM_QUEUES-1:0];
wire [C_NUM_QUEUES-1:0] in_tvalid;
wire [C_NUM_QUEUES-1:0] in_tlast;
wire [C_AXIS_DATA_WIDTH-1:0] fifo_out_tdata [C_NUM_QUEUES-1:0];
wire [C_AXIS_DATA_WIDTH/8-1:0] fifo_out_tkeep [C_NUM_QUEUES-1:0];
wire [C_AXIS_TUSER_WIDTH-1:0] fifo_out_tuser [C_NUM_QUEUES-1:0];
wire [C_NUM_QUEUES-1:0] fifo_out_tlast;
reg [C_NUM_QUEUES-1:0] rd_en;
wire [C_NUM_QUEUES_WIDTH-1:0] cur_queue_plus1;
reg [C_NUM_QUEUES_WIDTH-1:0] cur_queue, cur_queue_next;
reg state, state_next;
generate
genvar i;
for (i=0; i<C_NUM_QUEUES; i=i+1) begin:
out_arb_queues
fallthrough_small_fifo #(
.WIDTH(C_AXIS_DATA_WIDTH+C_AXIS_DATA_WIDTH/8+C_AXIS_TUSER_WIDTH+1),
.MAX_DEPTH_BITS(4)
) out_arb_fifo (
.dout ({fifo_out_tdata[i], fifo_out_tuser[i], fifo_out_tkeep[i], fifo_out_tlast[i]}),
.rd_en (rd_en[i]),
.din ({in_tdata[i], in_tuser[i], in_tkeep[i], in_tlast[i]}),
.wr_en (in_tvalid[i] & ~nearly_full[i]),
.full (),
.nearly_full (nearly_full[i]),
.empty (empty[i]),
.reset (~aresetn),
.clk (axis_clk)
);
end
endgenerate
assign in_tdata[0] = s_axis_tdata_0;
assign in_tkeep[0] = s_axis_tkeep_0;
assign in_tuser[0] = s_axis_tuser_0;
assign in_tlast[0] = s_axis_tlast_0;
assign in_tvalid[0] = s_axis_tvalid_0;
assign s_axis_tready_0 = ~nearly_full[0];
assign in_tdata[1] = s_axis_tdata_1;
assign in_tkeep[1] = s_axis_tkeep_1;
assign in_tuser[1] = s_axis_tuser_1;
assign in_tlast[1] = s_axis_tlast_1;
assign in_tvalid[1] = s_axis_tvalid_1;
assign s_axis_tready_1 = ~nearly_full[1];
assign in_tdata[2] = s_axis_tdata_2;
assign in_tkeep[2] = s_axis_tkeep_2;
assign in_tuser[2] = s_axis_tuser_2;
assign in_tlast[2] = s_axis_tlast_2;
assign in_tvalid[2] = s_axis_tvalid_2;
assign s_axis_tready_2 = ~nearly_full[2];
assign in_tdata[3] = s_axis_tdata_3;
assign in_tkeep[3] = s_axis_tkeep_3;
assign in_tuser[3] = s_axis_tuser_3;
assign in_tlast[3] = s_axis_tlast_3;
assign in_tvalid[3] = s_axis_tvalid_3;
assign s_axis_tready_3 = ~nearly_full[3];
assign cur_queue_plus1 = (cur_queue==C_NUM_QUEUES-1)? 0 : cur_queue+1;
assign m_axis_tdata = fifo_out_tdata[cur_queue];
assign m_axis_tuser = fifo_out_tuser[cur_queue];
assign m_axis_tkeep = fifo_out_tkeep[cur_queue];
assign m_axis_tlast = fifo_out_tlast[cur_queue];
assign m_axis_tvalid = ~empty[cur_queue] && m_axis_tready;
localparam IDLE=0,
WR_PKT=1;
always @(*) begin
state_next = state;
cur_queue_next = cur_queue;
rd_en = 0;
case (state)
IDLE: begin
if (!empty[cur_queue]) begin
if (m_axis_tready) begin
state_next = WR_PKT;
rd_en[cur_queue] = 1;
end
end
else begin
cur_queue_next = cur_queue_plus1;
end
end
WR_PKT: begin
if (m_axis_tready & m_axis_tlast) begin
state_next = IDLE;
rd_en[cur_queue] = 1;
cur_queue_next = cur_queue_plus1;
end
else if (m_axis_tready && !empty[cur_queue]) begin
rd_en[cur_queue] = 1;
end
end
endcase
end
always @(posedge axis_clk) begin
if (~aresetn) begin
state <= IDLE;
cur_queue <= 0;
end
else begin
state <= state_next;
cur_queue <= cur_queue_next;
end
end
endmodule
`timescale 1ns / 1ps
`define DEF_MAC_ADDR 48
`define DEF_VLAN 32
`define DEF_ETHTYPE 16
`define TYPE_IPV4 16'h0008
`define TYPE_ARP 16'h0608
`define PROT_ICMP 8'h01
`define PROT_TCP 8'h06
`define PROT_UDP 8'h11
`define SUB_PARSE(idx) \
case(sub_parse_val_out_type_d1[idx]) \
2'b01: val_2B_nxt[sub_parse_val_out_seq_d1[idx]] = sub_parse_val_out_d1[idx][15:0]; \
2'b10: val_4B_nxt[sub_parse_val_out_seq_d1[idx]] = sub_parse_val_out_d1[idx][31:0]; \
2'b11: val_6B_nxt[sub_parse_val_out_seq_d1[idx]] = sub_parse_val_out_d1[idx][47:0]; \
endcase \
`define SWAP_BYTE_ORDER(idx) \
assign val_6B_swapped[idx] = { val_6B[idx][0+:8], \
val_6B[idx][8+:8], \
val_6B[idx][16+:8], \
val_6B[idx][24+:8], \
val_6B[idx][32+:8], \
val_6B[idx][40+:8]}; \
assign val_4B_swapped[idx] = { val_4B[idx][0+:8], \
val_4B[idx][8+:8], \
val_4B[idx][16+:8], \
val_4B[idx][24+:8]}; \
assign val_2B_swapped[idx] = { val_2B[idx][0+:8], \
val_2B[idx][8+:8]}; \
module parser_do_parsing #(
parameter C_AXIS_DATA_WIDTH = 512,
parameter C_AXIS_TUSER_WIDTH = 128,
parameter PKT_HDR_LEN = (6+4+2)*8*8+256, // check with the doc
parameter PARSER_MOD_ID = 3'b0,
parameter C_NUM_SEGS = 2,
parameter C_VLANID_WIDTH = 12,
parameter C_PARSER_RAM_WIDTH = 160
)
(
input axis_clk,
input aresetn,
input [C_NUM_SEGS*C_AXIS_DATA_WIDTH-1:0] tdata_segs,
input [C_AXIS_TUSER_WIDTH-1:0] tuser_1st,
input segs_valid,
input [C_PARSER_RAM_WIDTH-1:0] bram_in,
input bram_in_valid,
input stg_ready_in,
// phv output
output reg parser_valid,
output reg [PKT_HDR_LEN-1:0] pkt_hdr_vec,
// vlan output
output reg [C_VLANID_WIDTH-1:0] vlan_out,
output reg vlan_out_valid
);
integer i;
localparam IDLE=0,
WAIT_1CYCLE_RAM=1,
START_SUB_PARSE=2,
FINISH_SUB_PARSE=3,
GET_PHV_OUTPUT=4,
OUTPUT=5,
EMPTY_1=6;
//
reg [PKT_HDR_LEN-1:0] pkt_hdr_vec_next;
reg parser_valid_next;
reg [3:0] state, state_next;
reg [11:0] vlan_out_next;
reg vlan_out_valid_next;
// parsing actions
wire [15:0] parse_action [0:9]; // we have 10 parse action
assign parse_action[9] = bram_in[0+:16];
assign parse_action[8] = bram_in[16+:16];
assign parse_action[7] = bram_in[32+:16];
assign parse_action[6] = bram_in[48+:16];
assign parse_action[5] = bram_in[64+:16];
assign parse_action[4] = bram_in[80+:16];
assign parse_action[3] = bram_in[96+:16];
assign parse_action[2] = bram_in[112+:16];
assign parse_action[1] = bram_in[128+:16];
assign parse_action[0] = bram_in[144+:16];
reg [9:0] sub_parse_act_valid;
wire [47:0] sub_parse_val_out [0:9];
wire [9:0] sub_parse_val_out_valid;
wire [1:0] sub_parse_val_out_type [0:9];
wire [2:0] sub_parse_val_out_seq [0:9];
reg [47:0] sub_parse_val_out_d1 [0:9];
reg [9:0] sub_parse_val_out_valid_d1;
reg [1:0] sub_parse_val_out_type_d1 [0:9];
reg [2:0] sub_parse_val_out_seq_d1 [0:9];
reg [47:0] val_6B [0:7];
reg [31:0] val_4B [0:7];
reg [15:0] val_2B [0:7];
reg [47:0] val_6B_nxt [0:7];
reg [31:0] val_4B_nxt [0:7];
reg [15:0] val_2B_nxt [0:7];
wire [47:0] val_6B_swapped [0:7];
wire [31:0] val_4B_swapped [0:7];
wire [15:0] val_2B_swapped [0:7];
`SWAP_BYTE_ORDER(0)
`SWAP_BYTE_ORDER(1)
`SWAP_BYTE_ORDER(2)
`SWAP_BYTE_ORDER(3)
`SWAP_BYTE_ORDER(4)
`SWAP_BYTE_ORDER(5)
`SWAP_BYTE_ORDER(6)
`SWAP_BYTE_ORDER(7)
always @(*) begin
state_next = state;
//
parser_valid_next = 0;
pkt_hdr_vec_next = pkt_hdr_vec;
//
val_2B_nxt[0]=val_2B[0];
val_2B_nxt[1]=val_2B[1];
val_2B_nxt[2]=val_2B[2];
val_2B_nxt[3]=val_2B[3];
val_2B_nxt[4]=val_2B[4];
val_2B_nxt[5]=val_2B[5];
val_2B_nxt[6]=val_2B[6];
val_2B_nxt[7]=val_2B[7];
val_4B_nxt[0]=val_4B[0];
val_4B_nxt[1]=val_4B[1];
val_4B_nxt[2]=val_4B[2];
val_4B_nxt[3]=val_4B[3];
val_4B_nxt[4]=val_4B[4];
val_4B_nxt[5]=val_4B[5];
val_4B_nxt[6]=val_4B[6];
val_4B_nxt[7]=val_4B[7];
val_6B_nxt[0]=val_6B[0];
val_6B_nxt[1]=val_6B[1];
val_6B_nxt[2]=val_6B[2];
val_6B_nxt[3]=val_6B[3];
val_6B_nxt[4]=val_6B[4];
val_6B_nxt[5]=val_6B[5];
val_6B_nxt[6]=val_6B[6];
val_6B_nxt[7]=val_6B[7];
//
sub_parse_act_valid = 10'b0;
//
vlan_out_next = vlan_out;
vlan_out_valid_next = 0;
case (state)
IDLE: begin
if (segs_valid) begin
sub_parse_act_valid = 10'b1111111111;
vlan_out_next = tdata_segs[116+:12];
state_next = FINISH_SUB_PARSE;
end
end
FINISH_SUB_PARSE: begin
state_next = EMPTY_1;
end
EMPTY_1: begin
state_next = GET_PHV_OUTPUT;
`SUB_PARSE(0)
`SUB_PARSE(1)
`SUB_PARSE(2)
`SUB_PARSE(3)
`SUB_PARSE(4)
`SUB_PARSE(5)
`SUB_PARSE(6)
`SUB_PARSE(7)
`SUB_PARSE(8)
`SUB_PARSE(9)
vlan_out_valid_next = 1;
end
GET_PHV_OUTPUT: begin
pkt_hdr_vec_next ={val_6B_swapped[7], val_6B_swapped[6], val_6B_swapped[5], val_6B_swapped[4], val_6B_swapped[3], val_6B_swapped[2], val_6B_swapped[1], val_6B_swapped[0],
val_4B_swapped[7], val_4B_swapped[6], val_4B_swapped[5], val_4B_swapped[4], val_4B_swapped[3], val_4B_swapped[2], val_4B_swapped[1], val_4B_swapped[0],
val_2B_swapped[7], val_2B_swapped[6], val_2B_swapped[5], val_2B_swapped[4], val_2B_swapped[3], val_2B_swapped[2], val_2B_swapped[1], val_2B_swapped[0],
// Tao: manually set output port to 1 for eazy test
// {115{1'b0}}, vlan_id, 1'b0, tuser_1st[127:32], 8'h04, tuser_1st[23:0]};
{115{1'b0}}, vlan_out, 1'b0, tuser_1st[127:0]};
// {115{1'b0}}, vlan_id, 1'b0, tuser_1st};
// {128{1'b0}}, tuser_1st[127:32], 8'h04, tuser_1st[23:0]};
//
if (stg_ready_in) begin
parser_valid_next = 1;
state_next = IDLE;
end
else begin
state_next = OUTPUT;
end
end
OUTPUT: begin
if (stg_ready_in) begin
parser_valid_next = 1;
state_next = IDLE;
// zero out
val_2B_nxt[0]=0;
val_2B_nxt[1]=0;
val_2B_nxt[2]=0;
val_2B_nxt[3]=0;
val_2B_nxt[4]=0;
val_2B_nxt[5]=0;
val_2B_nxt[6]=0;
val_2B_nxt[7]=0;
val_4B_nxt[0]=0;
val_4B_nxt[1]=0;
val_4B_nxt[2]=0;
val_4B_nxt[3]=0;
val_4B_nxt[4]=0;
val_4B_nxt[5]=0;
val_4B_nxt[6]=0;
val_4B_nxt[7]=0;
val_6B_nxt[0]=0;
val_6B_nxt[1]=0;
val_6B_nxt[2]=0;
val_6B_nxt[3]=0;
val_6B_nxt[4]=0;
val_6B_nxt[5]=0;
val_6B_nxt[6]=0;
val_6B_nxt[7]=0;
end
end
endcase
end
always @(posedge axis_clk) begin
if (~aresetn) begin
state <= IDLE;
//
pkt_hdr_vec <= 0;
parser_valid <= 0;
//
vlan_out <= 0;
vlan_out_valid <= 0;
//
val_2B[0] <= 0;
val_2B[1] <= 0;
val_2B[2] <= 0;
val_2B[3] <= 0;
val_2B[4] <= 0;
val_2B[5] <= 0;
val_2B[6] <= 0;
val_2B[7] <= 0;
val_4B[0] <= 0;
val_4B[1] <= 0;
val_4B[2] <= 0;
val_4B[3] <= 0;
val_4B[4] <= 0;
val_4B[5] <= 0;
val_4B[6] <= 0;
val_4B[7] <= 0;
val_6B[0] <= 0;
val_6B[1] <= 0;
val_6B[2] <= 0;
val_6B[3] <= 0;
val_6B[4] <= 0;
val_6B[5] <= 0;
val_6B[6] <= 0;
val_6B[7] <= 0;
for (i=0; i<10; i=i+1) begin
sub_parse_val_out_d1[i] <= 0;
sub_parse_val_out_valid_d1 <= 0;
sub_parse_val_out_type_d1[i] <= 0;
sub_parse_val_out_seq_d1[i] <= 0 ;
end
end
else begin
state <= state_next;
//
pkt_hdr_vec <= pkt_hdr_vec_next;
parser_valid <= parser_valid_next;
//
vlan_out <= vlan_out_next;
vlan_out_valid <= vlan_out_valid_next;
//
val_2B[0] <= val_2B_nxt[0];
val_2B[1] <= val_2B_nxt[1];
val_2B[2] <= val_2B_nxt[2];
val_2B[3] <= val_2B_nxt[3];
val_2B[4] <= val_2B_nxt[4];
val_2B[5] <= val_2B_nxt[5];
val_2B[6] <= val_2B_nxt[6];
val_2B[7] <= val_2B_nxt[7];
val_4B[0] <= val_4B_nxt[0];
val_4B[1] <= val_4B_nxt[1];
val_4B[2] <= val_4B_nxt[2];
val_4B[3] <= val_4B_nxt[3];
val_4B[4] <= val_4B_nxt[4];
val_4B[5] <= val_4B_nxt[5];
val_4B[6] <= val_4B_nxt[6];
val_4B[7] <= val_4B_nxt[7];
val_6B[0] <= val_6B_nxt[0];
val_6B[1] <= val_6B_nxt[1];
val_6B[2] <= val_6B_nxt[2];
val_6B[3] <= val_6B_nxt[3];
val_6B[4] <= val_6B_nxt[4];
val_6B[5] <= val_6B_nxt[5];
val_6B[6] <= val_6B_nxt[6];
val_6B[7] <= val_6B_nxt[7];
//
for (i=0; i<10; i=i+1) begin
sub_parse_val_out_d1[i] <= sub_parse_val_out[i];
sub_parse_val_out_valid_d1 <= sub_parse_val_out_valid;
sub_parse_val_out_type_d1[i] <= sub_parse_val_out_type[i];
sub_parse_val_out_seq_d1[i] <= sub_parse_val_out_seq[i];
end
end
end
// =============================================================== //
// sub parser
generate
genvar index;
for (index=0; index<10; index=index+1) begin:
sub_op
sub_parser #(
.PKTS_HDR_LEN(),
.PARSE_ACT_LEN(),
.VAL_OUT_LEN()
)
sub_parser (
.clk (axis_clk),
.aresetn (aresetn),
.parse_act_valid (sub_parse_act_valid[index]),
.parse_act (parse_action[index]),
.pkts_hdr (tdata_segs),
.val_out_valid (sub_parse_val_out_valid[index]),
.val_out (sub_parse_val_out[index]),
.val_out_type (sub_parse_val_out_type[index]),
.val_out_seq (sub_parse_val_out_seq[index])
);
end
endgenerate
endmodule
`timescale 1ns / 1ps
module parser_do_parsing_top #(
parameter C_AXIS_DATA_WIDTH = 512,
parameter C_AXIS_TUSER_WIDTH = 128,
parameter PKT_HDR_LEN = (6+4+2)*8*8+256, // check with the doc
parameter C_NUM_SEGS = 2,
parameter C_PARSER_RAM_WIDTH = 160,
parameter C_VLANID_WIDTH = 12
)
(
input clk,
input aresetn,
input [C_NUM_SEGS*C_AXIS_DATA_WIDTH-1:0] segs_in,
input segs_in_valid,
input [C_AXIS_TUSER_WIDTH-1:0] tuser_1st_in,
input [C_PARSER_RAM_WIDTH-1:0] bram_in,
input bram_in_valid,
input stg_ready,
input stg_vlan_ready,
// phv output
output reg [PKT_HDR_LEN-1:0] pkt_hdr_vec,
output reg parser_valid,
output reg [C_VLANID_WIDTH-1:0] vlan_out,
output reg vlan_out_valid
);
wire [C_NUM_SEGS*C_AXIS_DATA_WIDTH-1:0] sub_parser_segs_in [0:1];
wire sub_parser_segs_in_valid [0:1];
wire [C_AXIS_TUSER_WIDTH-1:0] sub_parser_tuser_1st_in [0:1];
wire [C_PARSER_RAM_WIDTH-1:0] sub_parser_bram_in [0:1];
wire sub_parser_bram_in_valid [0:1];
reg [1:0] cur_queue, cur_queue_next;
wire [1:0] cur_queue_plus1;
assign cur_queue_plus1 = (cur_queue==1)?0:cur_queue+1;
assign sub_parser_segs_in[0] = segs_in;
assign sub_parser_segs_in[1] = segs_in;
// assign sub_parser_segs_in[2] = segs_in;
// assign sub_parser_segs_in[3] = segs_in;
assign sub_parser_segs_in_valid[0] = (cur_queue==0)?segs_in_valid:0;
assign sub_parser_segs_in_valid[1] = (cur_queue==1)?segs_in_valid:0;
// assign sub_parser_segs_in_valid[2] = (cur_queue==2)?segs_in_valid:0;
// assign sub_parser_segs_in_valid[3] = (cur_queue==3)?segs_in_valid:0;
assign sub_parser_tuser_1st_in[0] = tuser_1st_in;
assign sub_parser_tuser_1st_in[1] = tuser_1st_in;
// assign sub_parser_tuser_1st_in[2] = tuser_1st_in;
// assign sub_parser_tuser_1st_in[3] = tuser_1st_in;
assign sub_parser_bram_in[0] = bram_in;
assign sub_parser_bram_in[1] = bram_in;
// assign sub_parser_bram_in[2] = bram_in;
// assign sub_parser_bram_in[3] = bram_in;
assign sub_parser_bram_in_valid[0] = (cur_queue==0)?bram_in_valid:0;
assign sub_parser_bram_in_valid[1] = (cur_queue==1)?bram_in_valid:0;
// assign sub_parser_bram_in_valid[2] = (cur_queue==2)?bram_in_valid:0;
// assign sub_parser_bram_in_valid[3] = (cur_queue==3)?bram_in_valid:0;
always @(*) begin
cur_queue_next = cur_queue;
if (segs_in_valid) begin
cur_queue_next = cur_queue_plus1;
end
end
always @(posedge clk) begin
if (~aresetn) begin
cur_queue <= 0;
end
else begin
cur_queue <= cur_queue_next;
end
end
wire [1:0] nearly_full;
wire [1:0] empty;
wire [1:0] vlan_nearly_full;
wire [1:0] vlan_empty;
wire [PKT_HDR_LEN-1:0] sub_parser_pkt_hdr_out [0:1];
wire [1:0] sub_parser_pkt_hdr_valid;
wire [C_VLANID_WIDTH-1:0] sub_parser_vlan_out [0:1];
wire [1:0] sub_parser_vlan_out_valid;
reg [PKT_HDR_LEN-1:0] sub_parser_pkt_hdr_out_d1 [0:1];
reg [1:0] sub_parser_pkt_hdr_valid_d1;
reg [C_VLANID_WIDTH-1:0] sub_parser_vlan_out_d1 [0:1];
reg [1:0] sub_parser_vlan_out_valid_d1;
generate
genvar i;
for (i=0; i<2; i=i+1) begin:
sub_do_parsing
parser_do_parsing #(
.C_AXIS_DATA_WIDTH(C_AXIS_DATA_WIDTH),
.C_AXIS_TUSER_WIDTH(C_AXIS_TUSER_WIDTH)
)
phv_do_parsing (
.axis_clk (clk),
.aresetn (aresetn),
.tdata_segs (sub_parser_segs_in[i]),
.tuser_1st (sub_parser_tuser_1st_in[i]),
.segs_valid (sub_parser_segs_in_valid[i]),
.bram_in (sub_parser_bram_in[i]),
.bram_in_valid (sub_parser_bram_in_valid[i]),
.stg_ready_in (1'b1),
// output
.parser_valid (sub_parser_pkt_hdr_valid[i]),
.pkt_hdr_vec (sub_parser_pkt_hdr_out[i]),
.vlan_out (sub_parser_vlan_out[i]),
.vlan_out_valid (sub_parser_vlan_out_valid[i])
);
end
endgenerate
reg [1:0] out_cur_queue, out_cur_queue_next;
wire [1:0] out_cur_queue_plus1;
reg [PKT_HDR_LEN-1:0] pkt_hdr_vec_next;
reg parser_valid_next;
assign out_cur_queue_plus1 = (out_cur_queue==1)?0:out_cur_queue+1;
always @(*) begin
pkt_hdr_vec_next = pkt_hdr_vec;
parser_valid_next = 0;
out_cur_queue_next = out_cur_queue;
if (sub_parser_pkt_hdr_valid_d1[out_cur_queue]) begin
pkt_hdr_vec_next = sub_parser_pkt_hdr_out_d1[out_cur_queue];
parser_valid_next = 1;
out_cur_queue_next = out_cur_queue_plus1;
end
end
always @(posedge clk) begin
if (~aresetn) begin
out_cur_queue <= 0;
pkt_hdr_vec <= 0;
parser_valid <= 0;
end
else begin
out_cur_queue <= out_cur_queue_next;
pkt_hdr_vec <= pkt_hdr_vec_next;
parser_valid <= parser_valid_next;
end
end
reg [1:0] vlan_out_cur_queue, vlan_out_cur_queue_next;
wire [1:0] vlan_out_cur_queue_plus1;
reg [C_VLANID_WIDTH-1:0] vlan_out_next;
reg vlan_out_valid_next;
assign vlan_out_cur_queue_plus1 = (vlan_out_cur_queue==1)?0:vlan_out_cur_queue+1;
always @(*) begin
vlan_out_next = vlan_out;
vlan_out_valid_next = 0;
vlan_out_cur_queue_next = vlan_out_cur_queue;
if (sub_parser_vlan_out_valid_d1[vlan_out_cur_queue]) begin
vlan_out_next = sub_parser_vlan_out_d1[vlan_out_cur_queue];
vlan_out_valid_next = 1;
vlan_out_cur_queue_next = vlan_out_cur_queue_plus1;
end
end
always @(posedge clk) begin
if (~aresetn) begin
vlan_out_cur_queue <= 0;
vlan_out <= 0;
vlan_out_valid <= 0;
end
else begin
vlan_out_cur_queue <= vlan_out_cur_queue_next;
vlan_out <= vlan_out_next;
vlan_out_valid <= vlan_out_valid_next;
end
end
always @(posedge clk) begin
if (~aresetn) begin
sub_parser_pkt_hdr_out_d1[0] <= 0;
sub_parser_pkt_hdr_out_d1[1] <= 0;
sub_parser_pkt_hdr_valid_d1 <= 0;
sub_parser_vlan_out_d1[0] <= 0;
sub_parser_vlan_out_d1[1] <= 0;
sub_parser_vlan_out_valid_d1 <= 0;
end
else begin
sub_parser_pkt_hdr_out_d1[0] <= sub_parser_pkt_hdr_out[0];
sub_parser_pkt_hdr_out_d1[1] <= sub_parser_pkt_hdr_out[1];
sub_parser_pkt_hdr_valid_d1 <= sub_parser_pkt_hdr_valid;
sub_parser_vlan_out_d1[0] <= sub_parser_vlan_out[0];
sub_parser_vlan_out_d1[1] <= sub_parser_vlan_out[1];
sub_parser_vlan_out_valid_d1 <= sub_parser_vlan_out_valid;
end
end
/*
generate
for (i=0; i<2; i=i+1) begin:
out_arb_queues
fallthrough_small_fifo #(
.WIDTH(PKT_HDR_LEN),
.MAX_DEPTH_BITS(4)
) out_arb_fifo (
.dout (fifo_pkt_hdr_out[i]),
.rd_en (fifo_rd_en[i]),
.din (sub_parser_pkt_hdr_out[i]),
.wr_en (sub_parser_pkt_hdr_valid[i] & ~nearly_full[i]),
.full (),
.nearly_full (nearly_full[i]),
.empty (empty[i]),
.reset (~aresetn),
.clk (clk)
);
end
// vlan queue
for (i=0; i<2; i=i+1) begin:
vlan_out_arb_queues
fallthrough_small_fifo #(
.WIDTH(C_VLANID_WIDTH),
.MAX_DEPTH_BITS(4)
) vlan_out_arb_fifo (
.dout (fifo_vlan_out[i]),
.rd_en (fifo_vlan_rd_en[i]),
.din (sub_parser_vlan_out[i]),
.wr_en (sub_parser_vlan_out_valid[i] & ~vlan_nearly_full[i]),
.full (),
.nearly_full (vlan_nearly_full[i]),
.empty (vlan_empty[i]),
.reset (~aresetn),
.clk (clk)
);
end
endgenerate
localparam IDLE=0;
reg [1:0] out_cur_queue, out_cur_queue_next;
wire [1:0] out_cur_queue_plus1;
reg [1:0] vlan_out_cur_queue, vlan_out_cur_queue_next;
wire [1:0] vlan_out_cur_queue_plus1;
assign out_cur_queue_plus1 = (out_cur_queue==1)?0:out_cur_queue+1;
assign vlan_out_cur_queue_plus1 = (vlan_out_cur_queue==1)?0:vlan_out_cur_queue+1;
assign pkt_hdr_vec = fifo_pkt_hdr_out[out_cur_queue];
assign parser_valid = ~empty[out_cur_queue];
assign parser_ready = ~nearly_full[0] ||
~nearly_full[1];
// ~nearly_full[2] ||
// ~nearly_full[3];
assign vlan_out = fifo_vlan_out[vlan_out_cur_queue];
assign vlan_out_valid = ~vlan_empty[vlan_out_cur_queue];
always @(*) begin
out_cur_queue_next = out_cur_queue;
fifo_rd_en = 0;
if (!empty[out_cur_queue]) begin
if (stg_ready) begin
fifo_rd_en[out_cur_queue] = 1;
out_cur_queue_next = out_cur_queue_plus1;
end
end
end
always @(*) begin
vlan_out_cur_queue_next = vlan_out_cur_queue;
fifo_vlan_rd_en = 0;
if (!vlan_empty[vlan_out_cur_queue]) begin
if (stg_vlan_ready) begin
fifo_vlan_rd_en[out_cur_queue] = 1;
vlan_out_cur_queue_next = vlan_out_cur_queue_plus1;
end
end
end
always @(posedge clk) begin
if (~aresetn) begin
out_cur_queue <= 0;
vlan_out_cur_queue <= 0;
end
else begin
out_cur_queue <= out_cur_queue_next;
vlan_out_cur_queue <= vlan_out_cur_queue_next;
end
end*/
endmodule
`timescale 1ns / 1ps
module parser_top #(
parameter C_S_AXIS_DATA_WIDTH = 512,
parameter C_S_AXIS_TUSER_WIDTH = 128,
parameter PKT_HDR_LEN = (6+4+2)*8*8+256, // check with the doc
parameter PARSER_MOD_ID = 3'b0,
parameter C_NUM_SEGS = 2,
parameter C_VLANID_WIDTH = 12,
parameter C_PARSER_RAM_WIDTH = 160
)
(
input axis_clk,
input aresetn,
// input slvae axi stream
input [C_S_AXIS_DATA_WIDTH-1:0] s_axis_tdata,
input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_tuser,
input [C_S_AXIS_DATA_WIDTH/8-1:0] s_axis_tkeep,
input s_axis_tvalid,
input s_axis_tlast,
// input vlan info
input [C_VLANID_WIDTH-1:0] s_vlan_id,
input s_vlan_id_valid,
// output
output reg parser_valid,
output reg [PKT_HDR_LEN-1:0] pkt_hdr_vec,
// back-pressure signals
output s_axis_tready,
input stg_ready_in,
// output vlan
output reg[C_VLANID_WIDTH-1:0] out_vlan,
output reg out_vlan_valid,
input out_vlan_ready,
// output to different pkt fifo queues (i.e., data cache)
output [C_S_AXIS_DATA_WIDTH-1:0] m_axis_tdata_0,
output [C_S_AXIS_TUSER_WIDTH-1:0] m_axis_tuser_0,
output [C_S_AXIS_DATA_WIDTH/8-1:0] m_axis_tkeep_0,
output m_axis_tlast_0,
output m_axis_tvalid_0,
input m_axis_tready_0,
output [C_S_AXIS_DATA_WIDTH-1:0] m_axis_tdata_1,
output [C_S_AXIS_TUSER_WIDTH-1:0] m_axis_tuser_1,
output [C_S_AXIS_DATA_WIDTH/8-1:0] m_axis_tkeep_1,
output m_axis_tlast_1,
output m_axis_tvalid_1,
input m_axis_tready_1,
output [C_S_AXIS_DATA_WIDTH-1:0] m_axis_tdata_2,
output [C_S_AXIS_TUSER_WIDTH-1:0] m_axis_tuser_2,
output [C_S_AXIS_DATA_WIDTH/8-1:0] m_axis_tkeep_2,
output m_axis_tlast_2,
output m_axis_tvalid_2,
input m_axis_tready_2,
output [C_S_AXIS_DATA_WIDTH-1:0] m_axis_tdata_3,
output [C_S_AXIS_TUSER_WIDTH-1:0] m_axis_tuser_3,
output [C_S_AXIS_DATA_WIDTH/8-1:0] m_axis_tkeep_3,
output m_axis_tlast_3,
output m_axis_tvalid_3,
input m_axis_tready_3,
// ctrl path
input [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata,
input [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser,
input [C_S_AXIS_DATA_WIDTH/8-1:0] ctrl_s_axis_tkeep,
input ctrl_s_axis_tvalid,
input ctrl_s_axis_tlast,
output reg [C_S_AXIS_DATA_WIDTH-1:0] ctrl_m_axis_tdata,
output reg [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_m_axis_tuser,
output reg [C_S_AXIS_DATA_WIDTH/8-1:0] ctrl_m_axis_tkeep,
output reg ctrl_m_axis_tvalid,
output reg ctrl_m_axis_tlast
);
wire [C_NUM_SEGS*C_S_AXIS_DATA_WIDTH-1:0] segs_in;
reg [C_NUM_SEGS*C_S_AXIS_DATA_WIDTH-1:0] segs_in_r;
wire [C_S_AXIS_TUSER_WIDTH-1:0] tuser_1st_in;
reg [C_S_AXIS_TUSER_WIDTH-1:0] tuser_1st_in_r;
wire segs_in_valid;
reg segs_in_valid_r;
// paser bram out
wire [C_PARSER_RAM_WIDTH-1:0] bram_out_0;
reg [C_PARSER_RAM_WIDTH-1:0] bram_out_0_d1;
reg out_bram_valid, out_bram_valid_d1;
reg bram_ready, bram_ready_next;
assign s_axis_tready = bram_ready
&& m_axis_tready_0
&& m_axis_tready_1
&& m_axis_tready_2
&& m_axis_tready_3;
//
wire [3:0] m_axis_tready_queue;
assign m_axis_tready_queue[0] = m_axis_tready_0;
assign m_axis_tready_queue[1] = m_axis_tready_1;
assign m_axis_tready_queue[2] = m_axis_tready_2;
assign m_axis_tready_queue[3] = m_axis_tready_3;
localparam IDLE=0,
FLUSH_REST_PKTS=1;
reg [1:0] state, state_next;
reg [1:0] cur_queue, cur_queue_next;
wire [1:0] cur_queue_plus1;
assign cur_queue_plus1 = (cur_queue==3)?0:cur_queue+1;
// ==================================================
assign m_axis_tdata_0 = s_axis_tdata;
assign m_axis_tuser_0 = s_axis_tuser;
assign m_axis_tkeep_0 = s_axis_tkeep;
assign m_axis_tlast_0 = s_axis_tlast;
assign m_axis_tvalid_0 = (cur_queue==0?1:0) & s_axis_tvalid & m_axis_tready_0;
assign m_axis_tdata_1 = s_axis_tdata;
assign m_axis_tuser_1 = s_axis_tuser;
assign m_axis_tkeep_1 = s_axis_tkeep;
assign m_axis_tlast_1 = s_axis_tlast;
assign m_axis_tvalid_1 = (cur_queue==1?1:0) & s_axis_tvalid & m_axis_tready_1;
assign m_axis_tdata_2 = s_axis_tdata;
assign m_axis_tuser_2 = s_axis_tuser;
assign m_axis_tkeep_2 = s_axis_tkeep;
assign m_axis_tlast_2 = s_axis_tlast;
assign m_axis_tvalid_2 = (cur_queue==2?1:0) & s_axis_tvalid & m_axis_tready_2;
assign m_axis_tdata_3 = s_axis_tdata;
assign m_axis_tuser_3 = s_axis_tuser;
assign m_axis_tkeep_3 = s_axis_tkeep;
assign m_axis_tlast_3 = s_axis_tlast;
assign m_axis_tvalid_3 = (cur_queue==3?1:0) & s_axis_tvalid & m_axis_tready_3;
// ==================================================
always @(*) begin
state_next = state;
cur_queue_next = cur_queue;
case (state)
IDLE: begin
if (s_axis_tvalid) begin
if (m_axis_tready_queue[cur_queue]) begin
if (!s_axis_tlast) begin
state_next = FLUSH_REST_PKTS;
end
else begin
cur_queue_next = cur_queue_plus1;
end
end
end
end
FLUSH_REST_PKTS: begin
if (s_axis_tvalid) begin
if (m_axis_tready_queue[cur_queue]) begin
if (s_axis_tlast) begin
cur_queue_next = cur_queue_plus1;
state_next = IDLE;
end
end
end
end
endcase
end
always @(posedge axis_clk) begin
if (~aresetn) begin
state <= IDLE;
cur_queue <= 0;
end
else begin
state <= state_next;
cur_queue <= cur_queue_next;
end
end
// ==================================================
wire [C_VLANID_WIDTH-1:0] parser_out_vlan, vlan_fifo_out;
wire parser_out_vlan_valid;
// wire vlan_fifo_empty, vlan_fifo_nearly_full;
reg [C_VLANID_WIDTH-1:0] out_vlan_next;
reg out_vlan_valid_next;
// reg vlan_fifo_rd_en;
// wire [PKT_HDR_LEN-1:0] phv_fifo_out;
// wire phv_fifo_empty, phv_fifo_nearly_full;
// reg phv_fifo_rd_en;
localparam P_IDLE=0;
reg [1:0] p_state, p_state_next;
reg [1:0] p_cur_queue, p_cur_queue_next;
wire [1:0] p_cur_queue_plus1;
assign p_cur_queue_plus1 = (p_cur_queue==3)?0:p_cur_queue+1;
wire [3:0] p_cur_queue_val;
assign p_cur_queue_val[0] = (p_cur_queue==0)?1:0;
assign p_cur_queue_val[1] = (p_cur_queue==1)?1:0;
assign p_cur_queue_val[2] = (p_cur_queue==2)?1:0;
assign p_cur_queue_val[3] = (p_cur_queue==3)?1:0;
wire parser_valid_w;
wire [PKT_HDR_LEN-1:0] pkt_hdr_vec_w;
reg [PKT_HDR_LEN-1:0] pkt_hdr_vec_next, pkt_hdr_vec_r;
reg parser_valid_next, parser_valid_r;
/*
always @(*) begin
p_state_next = p_state;
p_cur_queue_next = p_cur_queue;
pkt_hdr_vec_next = pkt_hdr_vec;
parser_valid_next = 0;
case (p_state)
P_IDLE: begin
if (parser_valid_w) begin
pkt_hdr_vec_next = {pkt_hdr_vec_w[PKT_HDR_LEN-1:145], p_cur_queue_val, pkt_hdr_vec_w[0+:141]};
parser_valid_next = 1;
p_cur_queue_next = p_cur_queue_plus1;
end
end
endcase
end*/
always @(*) begin
p_cur_queue_next = p_cur_queue;
pkt_hdr_vec_next = pkt_hdr_vec_r;
parser_valid_next = 0;
if (parser_valid_w) begin
pkt_hdr_vec_next = {pkt_hdr_vec_w[PKT_HDR_LEN-1:145], p_cur_queue_val, pkt_hdr_vec_w[0+:141]};
parser_valid_next = 1;
p_cur_queue_next = p_cur_queue_plus1;
end
end
always @(*) begin
out_vlan_valid_next = 0;
out_vlan_next = out_vlan;
if (parser_out_vlan_valid) begin
out_vlan_valid_next = 1;
out_vlan_next = parser_out_vlan;
end
end
always @(posedge axis_clk) begin
if (~aresetn) begin
p_state <= P_IDLE;
p_cur_queue <= 0;
pkt_hdr_vec <= 0;
parser_valid <= 0;
out_vlan <= 0;
out_vlan_valid <= 0;
pkt_hdr_vec_r <= 0;
parser_valid_r <= 0;
end
else begin
p_state <= p_state_next;
p_cur_queue <= p_cur_queue_next;
pkt_hdr_vec_r <= pkt_hdr_vec_next;
parser_valid_r <= parser_valid_next;
pkt_hdr_vec <= pkt_hdr_vec_r;
parser_valid <= parser_valid_r;
out_vlan <= out_vlan_next;
out_vlan_valid <= out_vlan_valid_next;
end
end
//
always @(posedge axis_clk) begin
if (~aresetn) begin
segs_in_r <= 0;
tuser_1st_in_r <= 0;
segs_in_valid_r <= 0;
end
else begin
segs_in_r <= segs_in;
tuser_1st_in_r <= tuser_1st_in;
segs_in_valid_r <= segs_in_valid;
end
end
//
parser_wait_segs #(
)
get_segs
(
.axis_clk (axis_clk),
.aresetn (aresetn),
.s_axis_tdata (s_axis_tdata),
.s_axis_tuser (s_axis_tuser),
.s_axis_tkeep (s_axis_tkeep),
.s_axis_tvalid (s_axis_tvalid),
.s_axis_tlast (s_axis_tlast),
// output
.tdata_segs (segs_in),
.tuser_1st (tuser_1st_in),
.segs_valid (segs_in_valid)
);
parser_do_parsing_top #(
)
do_parsing
(
.clk (axis_clk),
.aresetn (aresetn),
.segs_in (segs_in_r),
.segs_in_valid (segs_in_valid_r),
.tuser_1st_in (tuser_1st_in_r),
.bram_in (bram_out_0_d1),
.bram_in_valid (out_bram_valid_d1),
.stg_ready (stg_ready_in),
.stg_vlan_ready (out_vlan_ready),
// output
.pkt_hdr_vec (pkt_hdr_vec_w),
.parser_valid (parser_valid_w),
.vlan_out (parser_out_vlan),
.vlan_out_valid (parser_out_vlan_valid)
);
//
localparam BRAM_IDLE=0,
BRAM_CYCLE_1=1,
BRAM_CYCLE_2=2,
BRAM_CYCLE_3=3;
reg [2:0] bram_state, bram_state_next;
reg out_bram_valid_next;
always @(*) begin
bram_state_next = bram_state;
out_bram_valid_next = 0;
bram_ready_next = bram_ready;
case (bram_state)
BRAM_IDLE: begin
if (s_vlan_id_valid) begin
bram_state_next = BRAM_CYCLE_1;
if (s_axis_tvalid && s_axis_tlast) begin
bram_ready_next = 0;
end
end
end
BRAM_CYCLE_1: begin
bram_state_next = BRAM_IDLE;
out_bram_valid_next = 1;
bram_ready_next = 1;
end
endcase
end
always @(posedge axis_clk) begin
if (~aresetn) begin
bram_state <= BRAM_IDLE;
out_bram_valid <= 0;
bram_ready <= 1;
out_bram_valid_d1 <= 0;
end
else begin
bram_state <= bram_state_next;
out_bram_valid <= out_bram_valid_next;
out_bram_valid_d1 <= out_bram_valid;
bram_out_0_d1 <= bram_out_0;
bram_ready <= bram_ready_next;
end
end
// fifo
/*
fallthrough_small_fifo #(
.WIDTH(PKT_HDR_LEN),
.MAX_DEPTH_BITS(4)
)
pkt_hdr_fifo (
.din (pkt_hdr_vec_w),
.wr_en (parser_valid_w),
.dout (phv_fifo_out),
.rd_en (phv_fifo_rd_en),
.full (),
.nearly_full (phv_fifo_nearly_full),
.empty (phv_fifo_empty),
.reset (~aresetn),
.clk (axis_clk)
);
fallthrough_small_fifo #(
.WIDTH(C_VLANID_WIDTH),
.MAX_DEPTH_BITS(4)
)
vlan_fifo (
.din (parser_out_vlan),
.wr_en (parser_out_vlan_valid),
.dout (vlan_fifo_out),
.rd_en (vlan_fifo_rd_en),
.full (),
.nearly_full (vlan_fifo_nearly_full),
.empty (vlan_fifo_empty),
.reset (~aresetn),
.clk (axis_clk)
);*/
/*================Control Path====================*/
wire [7:0] mod_id; //module ID
wire [15:0] control_flag; //dst udp port num
reg [7:0] c_index; //table index(addr)
reg c_wr_en; //enable table write(wen)
reg [159:0] entry_reg;
reg [2:0] c_state;
localparam IDLE_C = 1,
WRITE_C =2,
SU_WRITE_C = 3;
assign mod_id = ctrl_s_axis_tdata[368+:8];
assign control_flag = ctrl_s_axis_tdata[335:320];
//LE to BE switching
wire[C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_swapped;
assign ctrl_s_axis_tdata_swapped = { ctrl_s_axis_tdata[0+:8],
ctrl_s_axis_tdata[8+:8],
ctrl_s_axis_tdata[16+:8],
ctrl_s_axis_tdata[24+:8],
ctrl_s_axis_tdata[32+:8],
ctrl_s_axis_tdata[40+:8],
ctrl_s_axis_tdata[48+:8],
ctrl_s_axis_tdata[56+:8],
ctrl_s_axis_tdata[64+:8],
ctrl_s_axis_tdata[72+:8],
ctrl_s_axis_tdata[80+:8],
ctrl_s_axis_tdata[88+:8],
ctrl_s_axis_tdata[96+:8],
ctrl_s_axis_tdata[104+:8],
ctrl_s_axis_tdata[112+:8],
ctrl_s_axis_tdata[120+:8],
ctrl_s_axis_tdata[128+:8],
ctrl_s_axis_tdata[136+:8],
ctrl_s_axis_tdata[144+:8],
ctrl_s_axis_tdata[152+:8],
ctrl_s_axis_tdata[160+:8],
ctrl_s_axis_tdata[168+:8],
ctrl_s_axis_tdata[176+:8],
ctrl_s_axis_tdata[184+:8],
ctrl_s_axis_tdata[192+:8],
ctrl_s_axis_tdata[200+:8],
ctrl_s_axis_tdata[208+:8],
ctrl_s_axis_tdata[216+:8],
ctrl_s_axis_tdata[224+:8],
ctrl_s_axis_tdata[232+:8],
ctrl_s_axis_tdata[240+:8],
ctrl_s_axis_tdata[248+:8],
ctrl_s_axis_tdata[256+:8],
ctrl_s_axis_tdata[264+:8],
ctrl_s_axis_tdata[272+:8],
ctrl_s_axis_tdata[280+:8],
ctrl_s_axis_tdata[288+:8],
ctrl_s_axis_tdata[296+:8],
ctrl_s_axis_tdata[304+:8],
ctrl_s_axis_tdata[312+:8],
ctrl_s_axis_tdata[320+:8],
ctrl_s_axis_tdata[328+:8],
ctrl_s_axis_tdata[336+:8],
ctrl_s_axis_tdata[344+:8],
ctrl_s_axis_tdata[352+:8],
ctrl_s_axis_tdata[360+:8],
ctrl_s_axis_tdata[368+:8],
ctrl_s_axis_tdata[376+:8],
ctrl_s_axis_tdata[384+:8],
ctrl_s_axis_tdata[392+:8],
ctrl_s_axis_tdata[400+:8],
ctrl_s_axis_tdata[408+:8],
ctrl_s_axis_tdata[416+:8],
ctrl_s_axis_tdata[424+:8],
ctrl_s_axis_tdata[432+:8],
ctrl_s_axis_tdata[440+:8],
ctrl_s_axis_tdata[448+:8],
ctrl_s_axis_tdata[456+:8],
ctrl_s_axis_tdata[464+:8],
ctrl_s_axis_tdata[472+:8],
ctrl_s_axis_tdata[480+:8],
ctrl_s_axis_tdata[488+:8],
ctrl_s_axis_tdata[496+:8],
ctrl_s_axis_tdata[504+:8]
};
always @(posedge axis_clk or negedge aresetn) begin
if(~aresetn) begin
c_wr_en <= 1'b0;
c_index <= 4'b0;
ctrl_m_axis_tdata <= 0;
ctrl_m_axis_tuser <= 0;
ctrl_m_axis_tkeep <= 0;
ctrl_m_axis_tvalid <= 0;
ctrl_m_axis_tlast <= 0;
entry_reg <= 0;
c_state <= IDLE_C;
end
else begin
case(c_state)
IDLE_C: begin
if(ctrl_s_axis_tvalid && mod_id[2:0] == PARSER_MOD_ID && control_flag == 16'hf2f1)begin
c_wr_en <= 1'b0;
c_index <= ctrl_s_axis_tdata[384+:8];
ctrl_m_axis_tdata <= 0;
ctrl_m_axis_tuser <= 0;
ctrl_m_axis_tkeep <= 0;
ctrl_m_axis_tvalid <= 0;
ctrl_m_axis_tlast <= 0;
c_state <= WRITE_C;
end
else begin
c_wr_en <= 1'b0;
c_index <= 4'b0;
entry_reg <= 0;
ctrl_m_axis_tdata <= ctrl_s_axis_tdata;
ctrl_m_axis_tuser <= ctrl_s_axis_tuser;
ctrl_m_axis_tkeep <= ctrl_s_axis_tkeep;
ctrl_m_axis_tvalid <= ctrl_s_axis_tvalid;
ctrl_m_axis_tlast <= ctrl_s_axis_tlast;
c_state <= IDLE_C;
end
end
//support full table flush
WRITE_C: begin
if(ctrl_s_axis_tvalid) begin
c_wr_en <= 1'b1;
entry_reg <= ctrl_s_axis_tdata_swapped[511 -: 160];
if(ctrl_s_axis_tlast) begin
c_state <= IDLE_C;
end
else begin
c_state <= SU_WRITE_C;
end
end
else begin
c_wr_en <= 1'b0;
end
end
SU_WRITE_C: begin
if(ctrl_s_axis_tvalid) begin
entry_reg <= ctrl_s_axis_tdata_swapped[511 -: 160];
c_wr_en <= 1'b1;
c_index <= c_index + 1'b1;
if(ctrl_s_axis_tlast) begin
c_state <= IDLE_C;
end
else begin
c_state <= SU_WRITE_C;
end
end
else begin
c_wr_en <= 1'b0;
end
end
endcase
end
end
// =============================================================== //
// parse_act_ram_ip #(
// .C_INIT_FILE_NAME ("./parse_act_ram_init_file.mif"),
// .C_LOAD_INIT_FILE (1)
// )
parse_act_ram_ip
parse_act_ram_0
(
// write port
.clka (axis_clk),
.addra (c_index[4:0]),
.dina (entry_reg),
.ena (1'b1),
.wea (c_wr_en),
//
.clkb (axis_clk),
.addrb (s_vlan_id[8:4]), // TODO: note that we may change due to little or big endian
.doutb (bram_out_0),
.enb (1'b1) // always set to 1
);
endmodule
`timescale 1ns / 1ps
module parser_wait_segs #(
parameter C_AXIS_DATA_WIDTH = 512,
parameter C_AXIS_TUSER_WIDTH = 128,
parameter C_NUM_SEGS = 2
)
(
input axis_clk,
input aresetn,
//
input [C_AXIS_DATA_WIDTH-1:0] s_axis_tdata,
input [C_AXIS_TUSER_WIDTH-1:0] s_axis_tuser,
input [C_AXIS_DATA_WIDTH/8-1:0] s_axis_tkeep,
input s_axis_tvalid,
input s_axis_tlast,
//
output reg[C_NUM_SEGS*C_AXIS_DATA_WIDTH-1:0] tdata_segs,
output reg[C_AXIS_TUSER_WIDTH-1:0] tuser_1st,
output reg segs_valid
);
localparam WAIT_1ST_SEG=0,
WAIT_2ND_SEG=1,
WAIT_1CYCLE=2,
OUTPUT_SEGS=3,
WAIT_TILL_LAST=4;
reg [2:0] state, state_next;
reg [C_NUM_SEGS*C_AXIS_DATA_WIDTH-1:0] tdata_segs_next;
reg [C_AXIS_TUSER_WIDTH-1:0] tuser_1st_next;
reg segs_valid_next;
always @(*) begin
state_next = state;
tdata_segs_next = tdata_segs;
tuser_1st_next = tuser_1st;
segs_valid_next = 0;
case (state)
// at-most 2 segs
WAIT_1ST_SEG: begin
if (s_axis_tvalid) begin
tdata_segs_next[0*C_AXIS_DATA_WIDTH+:C_AXIS_DATA_WIDTH] = s_axis_tdata;
tuser_1st_next = s_axis_tuser;
if (s_axis_tlast) begin
state_next = WAIT_1CYCLE;
end
else begin
state_next = WAIT_2ND_SEG;
end
end
end
WAIT_1CYCLE: begin
segs_valid_next = 1;
state_next = WAIT_1ST_SEG;
end
WAIT_2ND_SEG: begin
if (s_axis_tvalid) begin
tdata_segs_next[1*C_AXIS_DATA_WIDTH+:C_AXIS_DATA_WIDTH] = s_axis_tdata;
segs_valid_next = 1;
if (s_axis_tlast) begin
state_next = WAIT_1ST_SEG;
end
else begin
state_next = WAIT_TILL_LAST;
end
end
end
WAIT_TILL_LAST: begin
if (s_axis_tvalid && s_axis_tlast) begin
state_next = WAIT_1ST_SEG;
end
end
endcase
end
always @(posedge axis_clk) begin
if (~aresetn) begin
state <= WAIT_1ST_SEG;
tdata_segs <= {C_NUM_SEGS*C_AXIS_DATA_WIDTH{1'b0}};
tuser_1st <= {C_AXIS_TUSER_WIDTH{1'b0}};
segs_valid <= 0;
end
else begin
state <= state_next;
tdata_segs <= tdata_segs_next;
tuser_1st <= tuser_1st_next;
segs_valid <= segs_valid_next;
end
end
endmodule
`timescale 1ns / 1ps
`define ETH_TYPE_IPV4 16'h0008
`define IPPROT_UDP 8'h11
`define CONTROL_PORT 16'hf2f1
module pkt_filter #(
parameter C_S_AXIS_DATA_WIDTH = 512,
parameter C_S_AXIS_TUSER_WIDTH = 128,
parameter C_VLANID_WIDTH = 12
)
(
input clk,
input aresetn,
input [31:0] vlan_drop_flags,
output [31:0] ctrl_token,
// input Slave AXI Stream
input [C_S_AXIS_DATA_WIDTH-1:0] s_axis_tdata,
input [((C_S_AXIS_DATA_WIDTH/8))-1:0] s_axis_tkeep,
input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_tuser,
input s_axis_tvalid,
output s_axis_tready,
input s_axis_tlast,
// output Master AXI Stream
output reg [C_S_AXIS_DATA_WIDTH-1:0] m_axis_tdata,
output reg [((C_S_AXIS_DATA_WIDTH/8))-1:0] m_axis_tkeep,
output reg [C_S_AXIS_TUSER_WIDTH-1:0] m_axis_tuser,
output reg m_axis_tvalid,
input m_axis_tready,
output reg m_axis_tlast,
output reg [C_VLANID_WIDTH-1:0] vlan_id,
output reg vlan_id_valid,
//TODO a back-pressure is needed?
output reg [C_S_AXIS_DATA_WIDTH-1:0] c_m_axis_tdata,
output reg [((C_S_AXIS_DATA_WIDTH/8))-1:0] c_m_axis_tkeep,
output reg [C_S_AXIS_TUSER_WIDTH-1:0] c_m_axis_tuser,
output reg c_m_axis_tvalid,
output reg c_m_axis_tlast
);
wire [C_S_AXIS_DATA_WIDTH-1:0] pkt_fifo_tdata;
wire [C_S_AXIS_DATA_WIDTH/8-1:0] pkt_fifo_tkeep;
wire [C_S_AXIS_TUSER_WIDTH-1:0] pkt_fifo_tuser;
wire pkt_fifo_tlast;
reg pkt_fifo_rd_en;
wire pkt_fifo_empty, pkt_fifo_full;
//
assign s_axis_tready = ~pkt_fifo_full;
fallthrough_small_fifo #(
.WIDTH(C_S_AXIS_DATA_WIDTH+C_S_AXIS_TUSER_WIDTH+C_S_AXIS_DATA_WIDTH/8+1),
.MAX_DEPTH_BITS(5)
)
seg_fifo (
.din ({s_axis_tdata, s_axis_tkeep, s_axis_tuser, s_axis_tlast}),
.wr_en (s_axis_tvalid),
//
.rd_en (pkt_fifo_rd_en),
.dout ({pkt_fifo_tdata, pkt_fifo_tkeep, pkt_fifo_tuser, pkt_fifo_tlast}),
//
.full (),
.prog_full (),
.nearly_full (pkt_fifo_full),
.empty (pkt_fifo_empty),
.reset (~aresetn),
.clk (clk)
);
localparam WAIT_FIRST_PKT=0,
DROP_PKT=1,
FLUSH_DATA=2,
FLUSH_CTL = 3;
reg [C_S_AXIS_DATA_WIDTH-1:0] r_tdata;
reg [((C_S_AXIS_DATA_WIDTH/8))-1:0] r_tkeep;
reg [C_S_AXIS_TUSER_WIDTH-1:0] r_tuser;
reg r_tvalid;
reg r_tlast;
reg r_s_tready;
reg [1:0] state, state_next;
//1 for control, 0 for data;
reg c_switch;
wire w_c_switch;
// vlan
reg vlan_id_valid_next;
//for security and reliability
reg [31:0] ctrl_token_r, ctrl_token_next;
//checkme: for dropping packets during reconf
wire [11:0] vlan_id_w;
wire [31:0] vlan_id_one_hot_w;
assign w_c_switch = c_switch;
assign ctrl_token = ctrl_token_r;
assign vlan_id_w = pkt_fifo_tdata[116 +: 12];
assign vlan_id_one_hot_w = (1'b1 << vlan_id_w[8:4]);
always @(*) begin
r_tdata = pkt_fifo_tdata;
r_tkeep = pkt_fifo_tkeep;
r_tuser = pkt_fifo_tuser;
r_tlast = pkt_fifo_tlast;
r_tvalid = 0;
// r_s_tready = m_axis_tready;
c_switch = 1'b0;
vlan_id_valid_next = 0;
pkt_fifo_rd_en = 0;
state_next = state;
ctrl_token_next = ctrl_token_r;
case (state)
WAIT_FIRST_PKT: begin
if (!pkt_fifo_empty) begin
if (m_axis_tready) begin
if ((pkt_fifo_tdata[143:128]==`ETH_TYPE_IPV4) &&
(pkt_fifo_tdata[223:216]==`IPPROT_UDP)) begin
//checkme: we put the security check here
// if(s_axis_tdata[335:320] == `CONTROL_PORT && cookie_w == cookie_val_d1) begin
if(pkt_fifo_tdata[335:320] == `CONTROL_PORT) begin
state_next = FLUSH_CTL;
c_switch = 1'b1;
//modify token once its true
ctrl_token_next = ctrl_token_r+1;
pkt_fifo_rd_en = 1;
r_tvalid = 1;
end
else if (!pkt_fifo_tlast) begin
//checkme: if this vlan is not configed, send it
// TODO: for validity check
//if((vlan_id_one_hot_w & vlan_drop_flags)==0) begin
if (1) begin
pkt_fifo_rd_en = 1;
r_tvalid = 1;
state_next = FLUSH_DATA;
c_switch = 1'b0;
vlan_id_valid_next = 1;
end
else begin
pkt_fifo_rd_en = 1;
state_next = DROP_PKT;
r_tvalid = 0;
end
end
else if (pkt_fifo_tlast) begin
pkt_fifo_rd_en = 1;
state_next = WAIT_FIRST_PKT;
c_switch = 1'b0;
vlan_id_valid_next = 1;
r_tvalid = 1;
//checkme: if this vlan is configed, drop it
//if((vlan_id_one_hot_w & vlan_drop_flags)!=0) begin
// r_tvalid = 0;
//end
end
end
else begin
pkt_fifo_rd_en = 1;
r_tvalid = 0;
state_next = DROP_PKT;
end
if (pkt_fifo_tlast) begin
state_next = WAIT_FIRST_PKT;
end
end
else begin
c_switch = 1'b0;
end
end
end
FLUSH_DATA: begin
if (!pkt_fifo_empty) begin
if (m_axis_tready) begin
r_tvalid = 1;
pkt_fifo_rd_en = 1;
if (pkt_fifo_tlast) begin
state_next = WAIT_FIRST_PKT;
end
end
end
end
FLUSH_CTL: begin
c_switch = 1'b1;
if (!pkt_fifo_empty) begin
r_tvalid = 1;
pkt_fifo_rd_en = 1;
if (pkt_fifo_tlast) begin
state_next = WAIT_FIRST_PKT;
end
end
end
DROP_PKT: begin
r_tvalid = 0;
if (!pkt_fifo_empty) begin
pkt_fifo_rd_en = 1;
if (pkt_fifo_tlast) begin
state_next = WAIT_FIRST_PKT;
end
end
end
endcase
end
always @(posedge clk or negedge aresetn) begin
if (~aresetn) begin
state <= WAIT_FIRST_PKT;
m_axis_tdata <= 0;
m_axis_tkeep <= 0;
m_axis_tuser <= 0;
m_axis_tlast <= 0;
m_axis_tvalid <= 0;
c_m_axis_tdata <= 0;
c_m_axis_tkeep <= 0;
c_m_axis_tuser <= 0;
c_m_axis_tlast <= 0;
c_m_axis_tvalid <= 0;
// s_axis_tready <= 0;
//
vlan_id <= 0;
vlan_id_valid <= 0;
//
ctrl_token_r <= 0;
end
else begin
state <= state_next;
ctrl_token_r <= ctrl_token_next;
if(!w_c_switch) begin // data pkt
m_axis_tdata <= r_tdata;
m_axis_tkeep <= r_tkeep;
m_axis_tuser <= r_tuser;
m_axis_tlast <= r_tlast;
m_axis_tvalid <= r_tvalid;
// s_axis_tready <= r_s_tready;
//reset control path output
c_m_axis_tdata <= 0;
c_m_axis_tkeep <= 0;
c_m_axis_tuser <= 0;
c_m_axis_tlast <= 0;
c_m_axis_tvalid <= 0;
vlan_id <= vlan_id_w;
vlan_id_valid <= vlan_id_valid_next;
end
else begin // ctrl pkt
m_axis_tdata <= 0;
m_axis_tkeep <= 0;
m_axis_tuser <= 0;
m_axis_tlast <= 0;
m_axis_tvalid <= 0;
//
c_m_axis_tdata <= r_tdata;
c_m_axis_tkeep <= r_tkeep;
c_m_axis_tuser <= r_tuser;
c_m_axis_tlast <= r_tlast;
c_m_axis_tvalid <= r_tvalid;
end
end
end
endmodule
`timescale 1ns / 1ps
module rmt_wrapper #(
// AXI-Lite parameters
// Width of AXI lite data bus in bits
parameter AXIL_DATA_WIDTH = 32,
// Width of AXI lite address bus in bits
parameter AXIL_ADDR_WIDTH = 16,
// Width of AXI lite wstrb (width of data bus in words)
parameter AXIL_STRB_WIDTH = (AXIL_DATA_WIDTH/8),
// AXI Stream parameters
// Slave
parameter C_S_AXIS_DATA_WIDTH = 512,
parameter C_S_AXIS_TUSER_WIDTH = 128,
// Master
// self-defined
parameter PHV_LEN = 48*8+32*8+16*8+256,
parameter KEY_LEN = 48*2+32*2+16*2+1,
parameter ACT_LEN = 25,
parameter KEY_OFF = 6*3+20,
parameter C_NUM_QUEUES = 4,
parameter C_VLANID_WIDTH = 12
)
(
input clk, // axis clk
input aresetn,
input [31:0] vlan_drop_flags,
output reg [31:0] ctrl_token,
/*
* input Slave AXI Stream
*/
input [C_S_AXIS_DATA_WIDTH-1:0] s_axis_tdata,
input [((C_S_AXIS_DATA_WIDTH/8))-1:0] s_axis_tkeep,
input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_tuser,
input s_axis_tvalid,
output s_axis_tready,
input s_axis_tlast,
/*
* output Master AXI Stream
*/
output [C_S_AXIS_DATA_WIDTH-1:0] m_axis_tdata,
output [((C_S_AXIS_DATA_WIDTH/8))-1:0] m_axis_tkeep,
output [C_S_AXIS_TUSER_WIDTH-1:0] m_axis_tuser,
output m_axis_tvalid,
input m_axis_tready,
output m_axis_tlast
);
reg [31:0] vlan_drop_flags_r;
wire [31:0] ctrl_token_r;
always @(posedge clk) begin
if (~aresetn) begin
vlan_drop_flags_r <= 0;
ctrl_token <= 0;
end
else begin
vlan_drop_flags_r <= vlan_drop_flags;
ctrl_token <= ctrl_token_r;
end
end
integer idx;
/*=================================================*/
localparam PKT_VEC_WIDTH = (6+4+2)*8*8+256;
wire stg0_phv_in_valid;
wire [PKT_VEC_WIDTH-1:0] stg0_phv_in;
// stage-related
wire [PKT_VEC_WIDTH-1:0] stg0_phv_out;
wire stg0_phv_out_valid;
wire [PKT_VEC_WIDTH-1:0] stg1_phv_out;
wire stg1_phv_out_valid;
wire [PKT_VEC_WIDTH-1:0] stg2_phv_out;
wire stg2_phv_out_valid;
wire [PKT_VEC_WIDTH-1:0] stg3_phv_out;
wire stg3_phv_out_valid;
// wire [PKT_VEC_WIDTH-1:0] stg4_phv_out;
// wire stg4_phv_out_valid;
reg [PKT_VEC_WIDTH-1:0] stg0_phv_in_d1;
reg [PKT_VEC_WIDTH-1:0] stg0_phv_out_d1;
reg [PKT_VEC_WIDTH-1:0] stg1_phv_out_d1;
reg [PKT_VEC_WIDTH-1:0] stg2_phv_out_d1;
reg [PKT_VEC_WIDTH-1:0] stg3_phv_out_d1;
reg stg0_phv_in_valid_d1;
reg stg0_phv_out_valid_d1;
reg stg1_phv_out_valid_d1;
reg stg2_phv_out_valid_d1;
reg stg3_phv_out_valid_d1;
//
wire [C_VLANID_WIDTH-1:0] stg0_vlan_in;
wire stg0_vlan_valid_in;
reg [C_VLANID_WIDTH-1:0] stg0_vlan_in_r;
reg stg0_vlan_valid_in_r;
wire stg0_vlan_ready;
wire [C_VLANID_WIDTH-1:0] stg0_vlan_out;
wire stg0_vlan_valid_out;
reg [C_VLANID_WIDTH-1:0] stg0_vlan_out_r;
reg stg0_vlan_valid_out_r;
wire stg1_vlan_ready;
wire [C_VLANID_WIDTH-1:0] stg1_vlan_out;
wire stg1_vlan_valid_out;
reg [C_VLANID_WIDTH-1:0] stg1_vlan_out_r;
reg stg1_vlan_valid_out_r;
wire stg2_vlan_ready;
wire [C_VLANID_WIDTH-1:0] stg2_vlan_out;
wire stg2_vlan_valid_out;
reg [C_VLANID_WIDTH-1:0] stg2_vlan_out_r;
reg stg2_vlan_valid_out_r;
wire stg3_vlan_ready;
wire [C_VLANID_WIDTH-1:0] stg3_vlan_out;
wire stg3_vlan_valid_out;
reg [C_VLANID_WIDTH-1:0] stg3_vlan_out_r;
reg stg3_vlan_valid_out_r;
wire last_stg_vlan_ready;
// back pressure signals
wire s_axis_tready_p;
wire stg0_ready;
wire stg1_ready;
wire stg2_ready;
wire stg3_ready;
wire last_stg_ready;
/*=================================================*/
wire [C_VLANID_WIDTH-1:0] s_vlan_id;
wire s_vlan_id_valid;
reg [C_VLANID_WIDTH-1:0] s_vlan_id_r;
reg s_vlan_id_valid_r;
//NOTE: to filter out packets other than UDP/IP.
wire [C_S_AXIS_DATA_WIDTH-1:0] s_axis_tdata_f;
wire [((C_S_AXIS_DATA_WIDTH/8))-1:0] s_axis_tkeep_f;
wire [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_tuser_f;
wire s_axis_tvalid_f;
wire s_axis_tready_f;
wire s_axis_tlast_f;
reg [C_S_AXIS_DATA_WIDTH-1:0] s_axis_tdata_f_reg;
reg [((C_S_AXIS_DATA_WIDTH/8))-1:0] s_axis_tkeep_f_reg;
reg [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_tuser_f_reg;
reg s_axis_tvalid_f_reg;
reg s_axis_tlast_f_reg;
//NOTE: filter control packets from data packets.
wire [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_1;
wire [((C_S_AXIS_DATA_WIDTH/8))-1:0] ctrl_s_axis_tkeep_1;
wire [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser_1;
wire ctrl_s_axis_tvalid_1;
wire ctrl_s_axis_tlast_1;
reg [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_1_r;
reg [((C_S_AXIS_DATA_WIDTH/8))-1:0] ctrl_s_axis_tkeep_1_r;
reg [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser_1_r;
reg ctrl_s_axis_tvalid_1_r;
reg ctrl_s_axis_tlast_1_r;
pkt_filter #(
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.C_S_AXIS_TUSER_WIDTH(C_S_AXIS_TUSER_WIDTH)
)pkt_filter
(
.clk(clk),
.aresetn(aresetn),
.vlan_drop_flags(vlan_drop_flags_r),
.ctrl_token(ctrl_token_r),
// input Slave AXI Stream
.s_axis_tdata(s_axis_tdata),
.s_axis_tkeep(s_axis_tkeep),
.s_axis_tuser(s_axis_tuser),
.s_axis_tvalid(s_axis_tvalid),
.s_axis_tready(s_axis_tready),
.s_axis_tlast(s_axis_tlast),
.vlan_id(s_vlan_id),
.vlan_id_valid(s_vlan_id_valid),
// output Master AXI Stream
.m_axis_tdata(s_axis_tdata_f),
.m_axis_tkeep(s_axis_tkeep_f),
.m_axis_tuser(s_axis_tuser_f),
.m_axis_tvalid(s_axis_tvalid_f),
// .m_axis_tready(s_axis_tready_f && s_axis_tready_p),
.m_axis_tready(s_axis_tready_p),
.m_axis_tlast(s_axis_tlast_f),
//control path
.c_m_axis_tdata(ctrl_s_axis_tdata_1),
.c_m_axis_tkeep(ctrl_s_axis_tkeep_1),
.c_m_axis_tuser(ctrl_s_axis_tuser_1),
.c_m_axis_tvalid(ctrl_s_axis_tvalid_1),
.c_m_axis_tlast(ctrl_s_axis_tlast_1)
);
// we will have multiple pkt fifos and phv fifos
// pkt fifo wires
wire [C_S_AXIS_DATA_WIDTH-1:0] pkt_fifo_tdata_out [C_NUM_QUEUES-1:0];
wire [C_S_AXIS_TUSER_WIDTH-1:0] pkt_fifo_tuser_out [C_NUM_QUEUES-1:0];
wire [C_S_AXIS_DATA_WIDTH/8-1:0] pkt_fifo_tkeep_out [C_NUM_QUEUES-1:0];
wire [C_NUM_QUEUES-1:0] pkt_fifo_tlast_out;
// output from parser
wire [C_S_AXIS_DATA_WIDTH-1:0] parser_m_axis_tdata [C_NUM_QUEUES-1:0];
wire [C_S_AXIS_TUSER_WIDTH-1:0] parser_m_axis_tuser [C_NUM_QUEUES-1:0];
wire [C_S_AXIS_DATA_WIDTH/8-1:0] parser_m_axis_tkeep [C_NUM_QUEUES-1:0];
wire [C_NUM_QUEUES-1:0] parser_m_axis_tlast;
wire [C_NUM_QUEUES-1:0] parser_m_axis_tvalid;
wire [C_NUM_QUEUES-1:0] pkt_fifo_rd_en;
wire [C_NUM_QUEUES-1:0] pkt_fifo_nearly_full;
wire [C_NUM_QUEUES-1:0] pkt_fifo_empty;
/*
generate
genvar i;
for (i=0; i<C_NUM_QUEUES; i=i+1) begin:
sub_pkt_fifo
fifo_generator_705b
pkt_fifo (
.clk (clk), // input wire clk
.srst (~aresetn), // input wire srst
.din ({parser_m_axis_tdata[i],
parser_m_axis_tuser[i],
parser_m_axis_tkeep[i],
parser_m_axis_tlast[i]}), // input wire [704 : 0] din
.wr_en (parser_m_axis_tvalid[i]), // input wire wr_en
.rd_en (pkt_fifo_rd_en[i]), // input wire rd_en
.dout ({pkt_fifo_tdata_out[i],
pkt_fifo_tuser_out[i],
pkt_fifo_tkeep_out[i],
pkt_fifo_tlast_out[i]}), // output wire [704 : 0] dout
.full (pkt_fifo_nearly_full[i]), // output wire full
.empty (pkt_fifo_empty[i]), // output wire empty
.wr_rst_busy (), // output wire wr_rst_busy
.rd_rst_busy () // output wire rd_rst_busy
);
end
endgenerate
*/
generate
genvar i;
for (i=0; i<C_NUM_QUEUES; i=i+1) begin:
sub_pkt_fifo
fallthrough_small_fifo #(
.WIDTH(C_S_AXIS_DATA_WIDTH+C_S_AXIS_TUSER_WIDTH+C_S_AXIS_DATA_WIDTH/8+1),
.MAX_DEPTH_BITS(4)
)
pkt_fifo (
.clk (clk), // input wire clk
.reset (~aresetn), // input wire srst
.din ({parser_m_axis_tdata[i],
parser_m_axis_tuser[i],
parser_m_axis_tkeep[i],
parser_m_axis_tlast[i]}), // input wire [704 : 0] din
.wr_en (parser_m_axis_tvalid[i]), // input wire wr_en
.rd_en (pkt_fifo_rd_en[i]), // input wire rd_en
.dout ({pkt_fifo_tdata_out[i],
pkt_fifo_tuser_out[i],
pkt_fifo_tkeep_out[i],
pkt_fifo_tlast_out[i]}), // output wire [704 : 0] dout
.full (),
.nearly_full (pkt_fifo_nearly_full[i]), // output wire full
.empty (pkt_fifo_empty[i]) // output wire empty
);
end
endgenerate
wire [PKT_VEC_WIDTH-1:0] last_stg_phv_out [C_NUM_QUEUES-1:0];
wire [PKT_VEC_WIDTH-1:0] phv_fifo_out [C_NUM_QUEUES-1:0];
wire last_stg_phv_out_valid [C_NUM_QUEUES-1:0];
wire phv_fifo_rd_en [C_NUM_QUEUES-1:0];
wire phv_fifo_nearly_full [C_NUM_QUEUES-1:0];
wire phv_fifo_empty [C_NUM_QUEUES-1:0];
wire [511:0] high_phv_out [C_NUM_QUEUES-1:0];
wire [511:0] low_phv_out [C_NUM_QUEUES-1:0];
assign phv_fifo_out[0] = {high_phv_out[0], low_phv_out[0]};
assign phv_fifo_out[1] = {high_phv_out[1], low_phv_out[1]};
assign phv_fifo_out[2] = {high_phv_out[2], low_phv_out[2]};
assign phv_fifo_out[3] = {high_phv_out[3], low_phv_out[3]};
assign s_axis_tready_f = (!pkt_fifo_nearly_full[0] ||
!pkt_fifo_nearly_full[1] ||
!pkt_fifo_nearly_full[2] ||
!pkt_fifo_nearly_full[3]) &&
(!phv_fifo_nearly_full[0] ||
!phv_fifo_nearly_full[1] ||
!phv_fifo_nearly_full[2] ||
!phv_fifo_nearly_full[3]);
generate
for (i=0; i<C_NUM_QUEUES; i=i+1) begin:
sub_phv_fifo_1
fallthrough_small_fifo #(
.WIDTH(512),
.MAX_DEPTH_BITS(6)
)
phv_fifo_1 (
.clk (clk),
.reset (~aresetn),
.din (last_stg_phv_out[i][511:0]),
.wr_en (last_stg_phv_out_valid[i]),
.rd_en (phv_fifo_rd_en[i]),
.dout (low_phv_out[i]),
.full (),
.nearly_full (phv_fifo_nearly_full[i]),
.empty (phv_fifo_empty[i])
);
/*
fifo_generator_512b
phv_fifo_1 (
.clk (clk), // input wire clk
.srst (~aresetn), // input wire srst
.din (last_stg_phv_out[i][511:0]), // input wire [511 : 0] din
.wr_en (last_stg_phv_out_valid[i]), // input wire wr_en
.rd_en (phv_fifo_rd_en[i]), // input wire rd_en
.dout (low_phv_out[i]), // output wire [511 : 0] dout
.full (phv_fifo_nearly_full[i]), // output wire full
.empty (phv_fifo_empty[i]), // output wire empty
.wr_rst_busy (), // output wire wr_rst_busy
.rd_rst_busy () // output wire rd_rst_busy
);*/
end
endgenerate
generate
for (i=0; i<C_NUM_QUEUES; i=i+1) begin:
sub_phv_fifo_2
fallthrough_small_fifo #(
.WIDTH(512),
.MAX_DEPTH_BITS(6)
)
phv_fifo_2 (
.clk (clk),
.reset (~aresetn),
.din (last_stg_phv_out[i][1023:512]),
.wr_en (last_stg_phv_out_valid[i]),
.rd_en (phv_fifo_rd_en[i]),
.dout (high_phv_out[i]),
.full (),
.nearly_full (),
.empty ()
);
/*
fifo_generator_512b
phv_fifo_2 (
.clk (clk), // input wire clk
.srst (~aresetn), // input wire srst
.din (last_stg_phv_out[i][1023:512]), // input wire [521 : 0] din
.wr_en (last_stg_phv_out_valid[i]), // input wire wr_en
.rd_en (phv_fifo_rd_en[i]), // input wire rd_en
.dout (high_phv_out[i]), // output wire [521 : 0] dout
.full (), // output wire full
.empty (), // output wire empty
.wr_rst_busy (), // output wire wr_rst_busy
.rd_rst_busy () // output wire rd_rst_busy
);*/
end
endgenerate
wire [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_2;
wire [((C_S_AXIS_DATA_WIDTH/8))-1:0] ctrl_s_axis_tkeep_2;
wire [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser_2;
wire ctrl_s_axis_tvalid_2;
wire ctrl_s_axis_tlast_2;
reg [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_2_r;
reg [((C_S_AXIS_DATA_WIDTH/8))-1:0] ctrl_s_axis_tkeep_2_r;
reg [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser_2_r;
reg ctrl_s_axis_tvalid_2_r;
reg ctrl_s_axis_tlast_2_r;
wire [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_3;
wire [((C_S_AXIS_DATA_WIDTH/8))-1:0] ctrl_s_axis_tkeep_3;
wire [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser_3;
wire ctrl_s_axis_tvalid_3;
wire ctrl_s_axis_tlast_3;
reg [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_3_r;
reg [((C_S_AXIS_DATA_WIDTH/8))-1:0] ctrl_s_axis_tkeep_3_r;
reg [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser_3_r;
reg ctrl_s_axis_tvalid_3_r;
reg ctrl_s_axis_tlast_3_r;
wire [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_4;
wire [((C_S_AXIS_DATA_WIDTH/8))-1:0] ctrl_s_axis_tkeep_4;
wire [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser_4;
wire ctrl_s_axis_tvalid_4;
wire ctrl_s_axis_tlast_4;
reg [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_4_r;
reg [((C_S_AXIS_DATA_WIDTH/8))-1:0] ctrl_s_axis_tkeep_4_r;
reg [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser_4_r;
reg ctrl_s_axis_tvalid_4_r;
reg ctrl_s_axis_tlast_4_r;
wire [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_5;
wire [((C_S_AXIS_DATA_WIDTH/8))-1:0] ctrl_s_axis_tkeep_5;
wire [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser_5;
wire ctrl_s_axis_tvalid_5;
wire ctrl_s_axis_tlast_5;
reg [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_5_r;
reg [((C_S_AXIS_DATA_WIDTH/8))-1:0] ctrl_s_axis_tkeep_5_r;
reg [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser_5_r;
reg ctrl_s_axis_tvalid_5_r;
reg ctrl_s_axis_tlast_5_r;
wire [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_6;
wire [((C_S_AXIS_DATA_WIDTH/8))-1:0] ctrl_s_axis_tkeep_6;
wire [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser_6;
wire ctrl_s_axis_tvalid_6;
wire ctrl_s_axis_tlast_6;
reg [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_6_r;
reg [((C_S_AXIS_DATA_WIDTH/8))-1:0] ctrl_s_axis_tkeep_6_r;
reg [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser_6_r;
reg ctrl_s_axis_tvalid_6_r;
reg ctrl_s_axis_tlast_6_r;
wire [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_7;
wire [((C_S_AXIS_DATA_WIDTH/8))-1:0] ctrl_s_axis_tkeep_7;
wire [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser_7;
wire ctrl_s_axis_tvalid_7;
wire ctrl_s_axis_tlast_7;
reg [C_S_AXIS_DATA_WIDTH-1:0] ctrl_s_axis_tdata_7_r;
reg [((C_S_AXIS_DATA_WIDTH/8))-1:0] ctrl_s_axis_tkeep_7_r;
reg [C_S_AXIS_TUSER_WIDTH-1:0] ctrl_s_axis_tuser_7_r;
reg ctrl_s_axis_tvalid_7_r;
reg ctrl_s_axis_tlast_7_r;
parser_top #(
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH), //for 100g mac exclusively
.C_S_AXIS_TUSER_WIDTH(),
.PKT_HDR_LEN()
)
phv_parser
(
.axis_clk (clk),
.aresetn (aresetn),
// input slvae axi stream
.s_axis_tdata (s_axis_tdata_f_reg),
.s_axis_tuser (s_axis_tuser_f_reg),
.s_axis_tkeep (s_axis_tkeep_f_reg),
// .s_axis_tvalid (s_axis_tvalid_f_reg & s_axis_tready_f),
.s_axis_tvalid (s_axis_tvalid_f_reg),
.s_axis_tlast (s_axis_tlast_f_reg),
.s_axis_tready (s_axis_tready_p),
.s_vlan_id (s_vlan_id_r),
.s_vlan_id_valid (s_vlan_id_valid_r),
// output
.parser_valid (stg0_phv_in_valid),
.pkt_hdr_vec (stg0_phv_in),
.out_vlan (stg0_vlan_in),
.out_vlan_valid (stg0_vlan_valid_in),
.out_vlan_ready (stg0_vlan_ready),
//
.stg_ready_in (stg0_ready),
// output to different pkt fifos
.m_axis_tdata_0 (parser_m_axis_tdata[0]),
.m_axis_tuser_0 (parser_m_axis_tuser[0]),
.m_axis_tkeep_0 (parser_m_axis_tkeep[0]),
.m_axis_tlast_0 (parser_m_axis_tlast[0]),
.m_axis_tvalid_0 (parser_m_axis_tvalid[0]),
.m_axis_tready_0 (~pkt_fifo_nearly_full[0]),
.m_axis_tdata_1 (parser_m_axis_tdata[1]),
.m_axis_tuser_1 (parser_m_axis_tuser[1]),
.m_axis_tkeep_1 (parser_m_axis_tkeep[1]),
.m_axis_tlast_1 (parser_m_axis_tlast[1]),
.m_axis_tvalid_1 (parser_m_axis_tvalid[1]),
.m_axis_tready_1 (~pkt_fifo_nearly_full[1]),
.m_axis_tdata_2 (parser_m_axis_tdata[2]),
.m_axis_tuser_2 (parser_m_axis_tuser[2]),
.m_axis_tkeep_2 (parser_m_axis_tkeep[2]),
.m_axis_tlast_2 (parser_m_axis_tlast[2]),
.m_axis_tvalid_2 (parser_m_axis_tvalid[2]),
.m_axis_tready_2 (~pkt_fifo_nearly_full[2]),
.m_axis_tdata_3 (parser_m_axis_tdata[3]),
.m_axis_tuser_3 (parser_m_axis_tuser[3]),
.m_axis_tkeep_3 (parser_m_axis_tkeep[3]),
.m_axis_tlast_3 (parser_m_axis_tlast[3]),
.m_axis_tvalid_3 (parser_m_axis_tvalid[3]),
.m_axis_tready_3 (~pkt_fifo_nearly_full[3]),
// control path
.ctrl_s_axis_tdata(ctrl_s_axis_tdata_1_r),
.ctrl_s_axis_tuser(ctrl_s_axis_tuser_1_r),
.ctrl_s_axis_tkeep(ctrl_s_axis_tkeep_1_r),
.ctrl_s_axis_tlast(ctrl_s_axis_tlast_1_r),
.ctrl_s_axis_tvalid(ctrl_s_axis_tvalid_1_r),
.ctrl_m_axis_tdata(ctrl_s_axis_tdata_2),
.ctrl_m_axis_tuser(ctrl_s_axis_tuser_2),
.ctrl_m_axis_tkeep(ctrl_s_axis_tkeep_2),
.ctrl_m_axis_tlast(ctrl_s_axis_tlast_2),
.ctrl_m_axis_tvalid(ctrl_s_axis_tvalid_2)
);
stage #(
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.STAGE_ID(0)
)
stage0
(
.axis_clk (clk),
.aresetn (aresetn),
// input
.phv_in (stg0_phv_in_d1),
.phv_in_valid (stg0_phv_in_valid_d1),
.vlan_in (stg0_vlan_in_r),
.vlan_valid_in (stg0_vlan_valid_in_r),
.vlan_ready_out (stg0_vlan_ready),
// output
.vlan_out (stg0_vlan_out),
.vlan_valid_out (stg0_vlan_valid_out),
.vlan_out_ready (stg1_vlan_ready),
// output
.phv_out (stg0_phv_out),
.phv_out_valid (stg0_phv_out_valid),
// back-pressure signals
.stage_ready_out (stg0_ready),
.stage_ready_in (stg1_ready),
// control path
.c_s_axis_tdata(ctrl_s_axis_tdata_2_r),
.c_s_axis_tuser(ctrl_s_axis_tuser_2_r),
.c_s_axis_tkeep(ctrl_s_axis_tkeep_2_r),
.c_s_axis_tlast(ctrl_s_axis_tlast_2_r),
.c_s_axis_tvalid(ctrl_s_axis_tvalid_2_r),
.c_m_axis_tdata(ctrl_s_axis_tdata_3),
.c_m_axis_tuser(ctrl_s_axis_tuser_3),
.c_m_axis_tkeep(ctrl_s_axis_tkeep_3),
.c_m_axis_tlast(ctrl_s_axis_tlast_3),
.c_m_axis_tvalid(ctrl_s_axis_tvalid_3)
);
stage #(
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.STAGE_ID(1)
)
stage1
(
.axis_clk (clk),
.aresetn (aresetn),
// input
.phv_in (stg0_phv_out_d1),
.phv_in_valid (stg0_phv_out_valid_d1),
.vlan_in (stg0_vlan_out_r),
.vlan_valid_in (stg0_vlan_valid_out_r),
.vlan_ready_out (stg1_vlan_ready),
// output
.vlan_out (stg1_vlan_out),
.vlan_valid_out (stg1_vlan_valid_out),
.vlan_out_ready (stg2_vlan_ready),
// output
.phv_out (stg1_phv_out),
.phv_out_valid (stg1_phv_out_valid),
// back-pressure signals
.stage_ready_out (stg1_ready),
.stage_ready_in (stg2_ready),
// control path
.c_s_axis_tdata(ctrl_s_axis_tdata_3_r),
.c_s_axis_tuser(ctrl_s_axis_tuser_3_r),
.c_s_axis_tkeep(ctrl_s_axis_tkeep_3_r),
.c_s_axis_tlast(ctrl_s_axis_tlast_3_r),
.c_s_axis_tvalid(ctrl_s_axis_tvalid_3_r),
.c_m_axis_tdata(ctrl_s_axis_tdata_4),
.c_m_axis_tuser(ctrl_s_axis_tuser_4),
.c_m_axis_tkeep(ctrl_s_axis_tkeep_4),
.c_m_axis_tlast(ctrl_s_axis_tlast_4),
.c_m_axis_tvalid(ctrl_s_axis_tvalid_4)
);
stage #(
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.STAGE_ID(2)
)
stage2
(
.axis_clk (clk),
.aresetn (aresetn),
// input
.phv_in (stg1_phv_out_d1),
.phv_in_valid (stg1_phv_out_valid_d1),
.vlan_in (stg1_vlan_out_r),
.vlan_valid_in (stg1_vlan_valid_out_r),
.vlan_ready_out (stg2_vlan_ready),
// output
.vlan_out (stg2_vlan_out),
.vlan_valid_out (stg2_vlan_valid_out),
.vlan_out_ready (stg3_vlan_ready),
// output
.phv_out (stg2_phv_out),
.phv_out_valid (stg2_phv_out_valid),
// back-pressure signals
.stage_ready_out (stg2_ready),
.stage_ready_in (stg3_ready),
// control path
.c_s_axis_tdata(ctrl_s_axis_tdata_4_r),
.c_s_axis_tuser(ctrl_s_axis_tuser_4_r),
.c_s_axis_tkeep(ctrl_s_axis_tkeep_4_r),
.c_s_axis_tlast(ctrl_s_axis_tlast_4_r),
.c_s_axis_tvalid(ctrl_s_axis_tvalid_4_r),
.c_m_axis_tdata(ctrl_s_axis_tdata_5),
.c_m_axis_tuser(ctrl_s_axis_tuser_5),
.c_m_axis_tkeep(ctrl_s_axis_tkeep_5),
.c_m_axis_tlast(ctrl_s_axis_tlast_5),
.c_m_axis_tvalid(ctrl_s_axis_tvalid_5)
);
stage #(
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.STAGE_ID(3)
)
stage3
(
.axis_clk (clk),
.aresetn (aresetn),
// input
.phv_in (stg2_phv_out_d1),
.phv_in_valid (stg2_phv_out_valid_d1),
.vlan_in (stg2_vlan_out_r),
.vlan_valid_in (stg2_vlan_valid_out_r),
.vlan_ready_out (stg3_vlan_ready),
// output
.vlan_out (stg3_vlan_out),
.vlan_valid_out (stg3_vlan_valid_out),
.vlan_out_ready (last_stg_vlan_ready),
// output
.phv_out (stg3_phv_out),
.phv_out_valid (stg3_phv_out_valid),
// back-pressure signals
.stage_ready_out (stg3_ready),
.stage_ready_in (last_stg_ready),
// control path
.c_s_axis_tdata(ctrl_s_axis_tdata_5_r),
.c_s_axis_tuser(ctrl_s_axis_tuser_5_r),
.c_s_axis_tkeep(ctrl_s_axis_tkeep_5_r),
.c_s_axis_tlast(ctrl_s_axis_tlast_5_r),
.c_s_axis_tvalid(ctrl_s_axis_tvalid_5_r),
.c_m_axis_tdata(ctrl_s_axis_tdata_6),
.c_m_axis_tuser(ctrl_s_axis_tuser_6),
.c_m_axis_tkeep(ctrl_s_axis_tkeep_6),
.c_m_axis_tlast(ctrl_s_axis_tlast_6),
.c_m_axis_tvalid(ctrl_s_axis_tvalid_6)
);
// [NOTICE] change to last stage
last_stage #(
.C_S_AXIS_DATA_WIDTH(512),
.STAGE_ID(4)
)
stage4
(
.axis_clk (clk),
.aresetn (aresetn),
// input
.phv_in (stg3_phv_out_d1),
.phv_in_valid (stg3_phv_out_valid_d1),
.vlan_in (stg3_vlan_out_r),
.vlan_valid_in (stg3_vlan_valid_out_r),
.vlan_ready_out (last_stg_vlan_ready),
// back-pressure signals
.stage_ready_out (last_stg_ready),
// .phv_in (stg0_phv_in_d1),
// .phv_in_valid (stg0_phv_in_valid_d1),
// .vlan_in (stg0_vlan_in_r),
// .vlan_valid_in (stg0_vlan_valid_in_r),
// .vlan_ready_out (stg0_vlan_ready),
// // back-pressure signals
// .stage_ready_out (stg0_ready),
// output
.phv_out_0 (last_stg_phv_out[0]),
.phv_out_valid_0 (last_stg_phv_out_valid[0]),
.phv_fifo_ready_0 (~phv_fifo_nearly_full[0]),
.phv_out_1 (last_stg_phv_out[1]),
.phv_out_valid_1 (last_stg_phv_out_valid[1]),
.phv_fifo_ready_1 (~phv_fifo_nearly_full[1]),
.phv_out_2 (last_stg_phv_out[2]),
.phv_out_valid_2 (last_stg_phv_out_valid[2]),
.phv_fifo_ready_2 (~phv_fifo_nearly_full[2]),
.phv_out_3 (last_stg_phv_out[3]),
.phv_out_valid_3 (last_stg_phv_out_valid[3]),
.phv_fifo_ready_3 (~phv_fifo_nearly_full[3]),
// control path
.c_s_axis_tdata(ctrl_s_axis_tdata_6_r),
.c_s_axis_tuser(ctrl_s_axis_tuser_6_r),
.c_s_axis_tkeep(ctrl_s_axis_tkeep_6_r),
.c_s_axis_tlast(ctrl_s_axis_tlast_6_r),
.c_s_axis_tvalid(ctrl_s_axis_tvalid_6_r),
.c_m_axis_tdata(ctrl_s_axis_tdata_7),
.c_m_axis_tuser(ctrl_s_axis_tuser_7),
.c_m_axis_tkeep(ctrl_s_axis_tkeep_7),
.c_m_axis_tlast(ctrl_s_axis_tlast_7),
.c_m_axis_tvalid(ctrl_s_axis_tvalid_7)
);
wire [C_S_AXIS_DATA_WIDTH-1:0] depar_out_tdata [C_NUM_QUEUES-1:0];
wire [((C_S_AXIS_DATA_WIDTH/8))-1:0] depar_out_tkeep [C_NUM_QUEUES-1:0];
wire [C_S_AXIS_TUSER_WIDTH-1:0] depar_out_tuser [C_NUM_QUEUES-1:0];
wire depar_out_tvalid [C_NUM_QUEUES-1:0];
wire depar_out_tlast [C_NUM_QUEUES-1:0];
wire depar_out_tready [C_NUM_QUEUES-1:0];
reg [C_S_AXIS_DATA_WIDTH-1:0] depar_out_tdata_d1 [C_NUM_QUEUES-1:0];
reg [((C_S_AXIS_DATA_WIDTH/8))-1:0] depar_out_tkeep_d1 [C_NUM_QUEUES-1:0];
reg [C_S_AXIS_TUSER_WIDTH-1:0] depar_out_tuser_d1 [C_NUM_QUEUES-1:0];
reg depar_out_tvalid_d1 [C_NUM_QUEUES-1:0];
reg depar_out_tlast_d1 [C_NUM_QUEUES-1:0];
// multiple deparser + output arbiter
generate
for (i=0; i<C_NUM_QUEUES; i=i+1) begin:
sub_deparser_top
deparser_top #(
.C_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.C_AXIS_TUSER_WIDTH(C_S_AXIS_TUSER_WIDTH),
.C_PKT_VEC_WIDTH(),
.DEPARSER_MOD_ID()
)
phv_deparser (
.axis_clk (clk),
.aresetn (aresetn),
//data plane
.pkt_fifo_tdata (pkt_fifo_tdata_out[i]),
.pkt_fifo_tkeep (pkt_fifo_tkeep_out[i]),
.pkt_fifo_tuser (pkt_fifo_tuser_out[i]),
.pkt_fifo_tlast (pkt_fifo_tlast_out[i]),
.pkt_fifo_empty (pkt_fifo_empty[i]),
// output from STAGE
.pkt_fifo_rd_en (pkt_fifo_rd_en[i]),
.phv_fifo_out (phv_fifo_out[i]),
.phv_fifo_empty (phv_fifo_empty[i]),
.phv_fifo_rd_en (phv_fifo_rd_en[i]),
// output
.depar_out_tdata (depar_out_tdata[i]),
.depar_out_tkeep (depar_out_tkeep[i]),
.depar_out_tuser (depar_out_tuser[i]),
.depar_out_tvalid (depar_out_tvalid[i]),
.depar_out_tlast (depar_out_tlast[i]),
// input
.depar_out_tready (depar_out_tready[i]),
//control path
.ctrl_s_axis_tdata(ctrl_s_axis_tdata_7_r),
.ctrl_s_axis_tuser(ctrl_s_axis_tuser_7_r),
.ctrl_s_axis_tkeep(ctrl_s_axis_tkeep_7_r),
.ctrl_s_axis_tvalid(ctrl_s_axis_tvalid_7_r),
.ctrl_s_axis_tlast(ctrl_s_axis_tlast_7_r)
);
end
endgenerate
// output arbiter
output_arbiter #(
.C_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.C_AXIS_TUSER_WIDTH(C_S_AXIS_TUSER_WIDTH)
)
out_arb (
.axis_clk (clk),
.aresetn (aresetn),
// output
.m_axis_tdata (m_axis_tdata),
.m_axis_tkeep (m_axis_tkeep),
.m_axis_tuser (m_axis_tuser),
.m_axis_tlast (m_axis_tlast),
.m_axis_tvalid (m_axis_tvalid),
.m_axis_tready (m_axis_tready),
// input from deparser
.s_axis_tdata_0 (depar_out_tdata_d1[0]),
.s_axis_tkeep_0 (depar_out_tkeep_d1[0]),
.s_axis_tuser_0 (depar_out_tuser_d1[0]),
.s_axis_tlast_0 (depar_out_tlast_d1[0]),
.s_axis_tvalid_0 (depar_out_tvalid_d1[0]),
.s_axis_tready_0 (depar_out_tready[0]),
.s_axis_tdata_1 (depar_out_tdata_d1[1]),
.s_axis_tkeep_1 (depar_out_tkeep_d1[1]),
.s_axis_tuser_1 (depar_out_tuser_d1[1]),
.s_axis_tlast_1 (depar_out_tlast_d1[1]),
.s_axis_tvalid_1 (depar_out_tvalid_d1[1]),
.s_axis_tready_1 (depar_out_tready[1]),
.s_axis_tdata_2 (depar_out_tdata_d1[2]),
.s_axis_tkeep_2 (depar_out_tkeep_d1[2]),
.s_axis_tuser_2 (depar_out_tuser_d1[2]),
.s_axis_tlast_2 (depar_out_tlast_d1[2]),
.s_axis_tvalid_2 (depar_out_tvalid_d1[2]),
.s_axis_tready_2 (depar_out_tready[2]),
.s_axis_tdata_3 (depar_out_tdata_d1[3]),
.s_axis_tkeep_3 (depar_out_tkeep_d1[3]),
.s_axis_tuser_3 (depar_out_tuser_d1[3]),
.s_axis_tlast_3 (depar_out_tlast_d1[3]),
.s_axis_tvalid_3 (depar_out_tvalid_d1[3]),
.s_axis_tready_3 (depar_out_tready[3])
);
always @(posedge clk) begin
if (~aresetn) begin
stg0_phv_in_valid_d1 <= 0;
stg0_phv_out_valid_d1 <= 0;
stg1_phv_out_valid_d1 <= 0;
stg2_phv_out_valid_d1 <= 0;
stg3_phv_out_valid_d1 <= 0;
stg0_phv_in_d1 <= 0;
stg0_phv_out_d1 <= 0;
stg1_phv_out_d1 <= 0;
stg2_phv_out_d1 <= 0;
stg3_phv_out_d1 <= 0;
//
s_axis_tdata_f_reg <= 0;
s_axis_tkeep_f_reg <= 0;
s_axis_tuser_f_reg <= 0;
s_axis_tlast_f_reg <= 0;
s_axis_tvalid_f_reg <= 0;
//
s_vlan_id_r <= 0;
s_vlan_id_valid_r <= 0;
//
stg0_vlan_in_r <= 0;
stg0_vlan_valid_in_r <= 0;
stg0_vlan_out_r <= 0;
stg0_vlan_valid_out_r <= 0;
stg1_vlan_out_r <= 0;
stg1_vlan_valid_out_r <= 0;
stg2_vlan_out_r <= 0;
stg2_vlan_valid_out_r <= 0;
stg3_vlan_out_r <= 0;
stg3_vlan_valid_out_r <= 0;
end
else begin
stg0_phv_in_valid_d1 <= stg0_phv_in_valid;
stg0_phv_out_valid_d1 <= stg0_phv_out_valid;
stg1_phv_out_valid_d1 <= stg1_phv_out_valid;
stg2_phv_out_valid_d1 <= stg2_phv_out_valid;
stg3_phv_out_valid_d1 <= stg3_phv_out_valid;
stg0_phv_in_d1 <= stg0_phv_in;
stg0_phv_out_d1 <= stg0_phv_out;
stg1_phv_out_d1 <= stg1_phv_out;
stg2_phv_out_d1 <= stg2_phv_out;
stg3_phv_out_d1 <= stg3_phv_out;
//
s_axis_tdata_f_reg <= s_axis_tdata_f;
s_axis_tkeep_f_reg <= s_axis_tkeep_f;
s_axis_tuser_f_reg <= s_axis_tuser_f;
s_axis_tlast_f_reg <= s_axis_tlast_f;
s_axis_tvalid_f_reg <= s_axis_tvalid_f;
//
s_vlan_id_r <= s_vlan_id;
s_vlan_id_valid_r <= s_vlan_id_valid;
//
stg0_vlan_in_r <= stg0_vlan_in;
stg0_vlan_valid_in_r <= stg0_vlan_valid_in;
stg0_vlan_out_r <= stg0_vlan_out;
stg0_vlan_valid_out_r <= stg0_vlan_valid_out;
stg1_vlan_out_r <= stg1_vlan_out;
stg1_vlan_valid_out_r <= stg1_vlan_valid_out;
stg2_vlan_out_r <= stg2_vlan_out;
stg2_vlan_valid_out_r <= stg2_vlan_valid_out;
stg3_vlan_out_r <= stg3_vlan_out;
stg3_vlan_valid_out_r <= stg3_vlan_valid_out;
end
end
// delay deparser out
always @(posedge clk) begin
if (~aresetn) begin
for (idx=0; idx<C_NUM_QUEUES; idx=idx+1) begin
depar_out_tdata_d1[idx] <= 0;
depar_out_tkeep_d1[idx] <= 0;
depar_out_tuser_d1[idx] <= 0;
depar_out_tvalid_d1[idx] <= 0;
depar_out_tlast_d1[idx] <= 0;
end
end
else begin
for (idx=0; idx<C_NUM_QUEUES; idx=idx+1) begin
depar_out_tdata_d1[idx] <= depar_out_tdata[idx];
depar_out_tkeep_d1[idx] <= depar_out_tkeep[idx];
depar_out_tuser_d1[idx] <= depar_out_tuser[idx];
depar_out_tvalid_d1[idx] <= depar_out_tvalid[idx];
depar_out_tlast_d1[idx] <= depar_out_tlast[idx];
end
end
end
always @(posedge clk) begin
if (~aresetn) begin
ctrl_s_axis_tdata_1_r <= 0;
ctrl_s_axis_tuser_1_r <= 0;
ctrl_s_axis_tkeep_1_r <= 0;
ctrl_s_axis_tlast_1_r <= 0;
ctrl_s_axis_tvalid_1_r <= 0;
ctrl_s_axis_tdata_2_r <= 0;
ctrl_s_axis_tuser_2_r <= 0;
ctrl_s_axis_tkeep_2_r <= 0;
ctrl_s_axis_tlast_2_r <= 0;
ctrl_s_axis_tvalid_2_r <= 0;
ctrl_s_axis_tdata_3_r <= 0;
ctrl_s_axis_tuser_3_r <= 0;
ctrl_s_axis_tkeep_3_r <= 0;
ctrl_s_axis_tlast_3_r <= 0;
ctrl_s_axis_tvalid_3_r <= 0;
ctrl_s_axis_tdata_4_r <= 0;
ctrl_s_axis_tuser_4_r <= 0;
ctrl_s_axis_tkeep_4_r <= 0;
ctrl_s_axis_tlast_4_r <= 0;
ctrl_s_axis_tvalid_4_r <= 0;
ctrl_s_axis_tdata_5_r <= 0;
ctrl_s_axis_tuser_5_r <= 0;
ctrl_s_axis_tkeep_5_r <= 0;
ctrl_s_axis_tlast_5_r <= 0;
ctrl_s_axis_tvalid_5_r <= 0;
ctrl_s_axis_tdata_6_r <= 0;
ctrl_s_axis_tuser_6_r <= 0;
ctrl_s_axis_tkeep_6_r <= 0;
ctrl_s_axis_tlast_6_r <= 0;
ctrl_s_axis_tvalid_6_r <= 0;
ctrl_s_axis_tdata_7_r <= 0;
ctrl_s_axis_tuser_7_r <= 0;
ctrl_s_axis_tkeep_7_r <= 0;
ctrl_s_axis_tlast_7_r <= 0;
ctrl_s_axis_tvalid_7_r <= 0;
end
else begin
ctrl_s_axis_tdata_1_r <= ctrl_s_axis_tdata_1;
ctrl_s_axis_tuser_1_r <= ctrl_s_axis_tuser_1;
ctrl_s_axis_tkeep_1_r <= ctrl_s_axis_tkeep_1;
ctrl_s_axis_tlast_1_r <= ctrl_s_axis_tlast_1;
ctrl_s_axis_tvalid_1_r <= ctrl_s_axis_tvalid_1;
ctrl_s_axis_tdata_2_r <= ctrl_s_axis_tdata_2;
ctrl_s_axis_tuser_2_r <= ctrl_s_axis_tuser_2;
ctrl_s_axis_tkeep_2_r <= ctrl_s_axis_tkeep_2;
ctrl_s_axis_tlast_2_r <= ctrl_s_axis_tlast_2;
ctrl_s_axis_tvalid_2_r <= ctrl_s_axis_tvalid_2;
ctrl_s_axis_tdata_3_r <= ctrl_s_axis_tdata_3;
ctrl_s_axis_tuser_3_r <= ctrl_s_axis_tuser_3;
ctrl_s_axis_tkeep_3_r <= ctrl_s_axis_tkeep_3;
ctrl_s_axis_tlast_3_r <= ctrl_s_axis_tlast_3;
ctrl_s_axis_tvalid_3_r <= ctrl_s_axis_tvalid_3;
ctrl_s_axis_tdata_4_r <= ctrl_s_axis_tdata_4;
ctrl_s_axis_tuser_4_r <= ctrl_s_axis_tuser_4;
ctrl_s_axis_tkeep_4_r <= ctrl_s_axis_tkeep_4;
ctrl_s_axis_tlast_4_r <= ctrl_s_axis_tlast_4;
ctrl_s_axis_tvalid_4_r <= ctrl_s_axis_tvalid_4;
ctrl_s_axis_tdata_5_r <= ctrl_s_axis_tdata_5;
ctrl_s_axis_tuser_5_r <= ctrl_s_axis_tuser_5;
ctrl_s_axis_tkeep_5_r <= ctrl_s_axis_tkeep_5;
ctrl_s_axis_tlast_5_r <= ctrl_s_axis_tlast_5;
ctrl_s_axis_tvalid_5_r <= ctrl_s_axis_tvalid_5;
ctrl_s_axis_tdata_6_r <= ctrl_s_axis_tdata_6;
ctrl_s_axis_tuser_6_r <= ctrl_s_axis_tuser_6;
ctrl_s_axis_tkeep_6_r <= ctrl_s_axis_tkeep_6;
ctrl_s_axis_tlast_6_r <= ctrl_s_axis_tlast_6;
ctrl_s_axis_tvalid_6_r <= ctrl_s_axis_tvalid_6;
ctrl_s_axis_tdata_7_r <= ctrl_s_axis_tdata_7;
ctrl_s_axis_tuser_7_r <= ctrl_s_axis_tuser_7;
ctrl_s_axis_tkeep_7_r <= ctrl_s_axis_tkeep_7;
ctrl_s_axis_tlast_7_r <= ctrl_s_axis_tlast_7;
ctrl_s_axis_tvalid_7_r <= ctrl_s_axis_tvalid_7;
end
end
endmodule
`timescale 1ns / 1ps
module stage #(
parameter C_S_AXIS_DATA_WIDTH = 512,
parameter C_S_AXIS_TUSER_WIDTH = 128,
parameter STAGE_ID = 0, // valid: 0-4
parameter PHV_LEN = 48*8+32*8+16*8+256,
parameter KEY_LEN = 48*2+32*2+16*2+1,
parameter ACT_LEN = 25,
parameter KEY_OFF = 6*3+20,
parameter C_VLANID_WIDTH = 12
)
(
input axis_clk,
input aresetn,
input [PHV_LEN-1:0] phv_in,
input phv_in_valid,
output stage_ready_out,
output vlan_ready_out,
input [C_VLANID_WIDTH-1:0] vlan_in,
input vlan_valid_in,
//
output [PHV_LEN-1:0] phv_out,
output phv_out_valid,
input stage_ready_in,
output [C_VLANID_WIDTH-1:0] vlan_out,
output vlan_valid_out,
input vlan_out_ready,
//control path
input [C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata,
input [C_S_AXIS_TUSER_WIDTH-1:0] c_s_axis_tuser,
input [C_S_AXIS_DATA_WIDTH/8-1:0] c_s_axis_tkeep,
input c_s_axis_tvalid,
input c_s_axis_tlast,
output [C_S_AXIS_DATA_WIDTH-1:0] c_m_axis_tdata,
output [C_S_AXIS_TUSER_WIDTH-1:0] c_m_axis_tuser,
output [C_S_AXIS_DATA_WIDTH/8-1:0] c_m_axis_tkeep,
output c_m_axis_tvalid,
output c_m_axis_tlast
);
//key_extract to lookup_engine
wire [KEY_LEN-1:0] key2lookup_key;
wire key2lookup_key_valid;
wire key2lookup_phv_valid;
wire [PHV_LEN-1:0] key2lookup_phv;
wire lookup2key_ready;
reg [KEY_LEN-1:0] key2lookup_key_r;
reg key2lookup_key_valid_r;
reg key2lookup_phv_valid_r;
reg [PHV_LEN-1:0] key2lookup_phv_r;
//control path 1 (key2lookup)
wire [C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata_1;
wire [((C_S_AXIS_DATA_WIDTH/8))-1:0] c_s_axis_tkeep_1;
wire [C_S_AXIS_TUSER_WIDTH-1:0] c_s_axis_tuser_1;
wire c_s_axis_tvalid_1;
wire c_s_axis_tlast_1;
//control path 2 (lkup2action)
wire [C_S_AXIS_DATA_WIDTH-1:0] c_s_axis_tdata_2;
wire [((C_S_AXIS_DATA_WIDTH/8))-1:0] c_s_axis_tkeep_2;
wire [C_S_AXIS_TUSER_WIDTH-1:0] c_s_axis_tuser_2;
wire c_s_axis_tvalid_2;
wire c_s_axis_tlast_2;
// vlan fifo
//lookup_engine to action_engine
wire [ACT_LEN*25-1:0] lookup2action_action;
wire lookup2action_action_valid;
wire [PHV_LEN-1:0] lookup2action_phv;
wire action2lookup_ready;
reg [ACT_LEN*25-1:0] lookup2action_action_r;
reg lookup2action_action_valid_r;
reg [PHV_LEN-1:0] lookup2action_phv_r;
wire [C_VLANID_WIDTH-1:0] act_vlan_out;
wire act_vlan_out_valid;
reg [C_VLANID_WIDTH-1:0] act_vlan_out_r;
reg act_vlan_out_valid_r;
wire act_vlan_ready;
always @(posedge axis_clk) begin
if (~aresetn) begin
key2lookup_key_r <= 0;
key2lookup_key_valid_r <= 0;
key2lookup_phv_valid_r <= 0;
key2lookup_phv_r <= 0;
lookup2action_action_r <= 0;
lookup2action_action_valid_r <= 0;
lookup2action_phv_r <= 0;
//
act_vlan_out_r <= 0;
act_vlan_out_valid_r <= 0;
end
else begin
key2lookup_key_r <= key2lookup_key;
key2lookup_key_valid_r <= key2lookup_key_valid;
key2lookup_phv_valid_r <= key2lookup_phv_valid;
key2lookup_phv_r <= key2lookup_phv;
lookup2action_action_r <= lookup2action_action;
lookup2action_action_valid_r <= lookup2action_action_valid;
lookup2action_phv_r <= lookup2action_phv;
//
act_vlan_out_r <= act_vlan_out;
act_vlan_out_valid_r <= act_vlan_out_valid;
end
end
//
key_extract_top #(
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.C_S_AXIS_TUSER_WIDTH(C_S_AXIS_TUSER_WIDTH),
.STAGE_ID(STAGE_ID),
.PHV_LEN(),
.KEY_LEN(KEY_LEN),
// format of KEY_OFF entry: |--3(6B)--|--3(6B)--|--3(4B)--|--3(4B)--|--3(2B)--|--3(2B)--|
.KEY_OFF(KEY_OFF),
.AXIL_WIDTH(),
.KEY_OFF_ADDR_WIDTH(),
.KEY_EX_ID()
)key_extract(
.clk(axis_clk),
.rst_n(aresetn),
.phv_in(phv_in),
.phv_valid_in(phv_in_valid),
.ready_out(stage_ready_out),
.vlan_in (vlan_in),
.vlan_in_valid (vlan_valid_in),
.vlan_ready (vlan_ready_out),
//
.phv_out(key2lookup_phv),
.phv_valid_out(key2lookup_phv_valid),
.key_out_masked(key2lookup_key),
.key_valid_out(key2lookup_key_valid),
.ready_in(lookup2key_ready),
//control path
.c_s_axis_tdata(c_s_axis_tdata),
.c_s_axis_tuser(c_s_axis_tuser),
.c_s_axis_tkeep(c_s_axis_tkeep),
.c_s_axis_tvalid(c_s_axis_tvalid),
.c_s_axis_tlast(c_s_axis_tlast),
.c_m_axis_tdata(c_s_axis_tdata_1),
.c_m_axis_tuser(c_s_axis_tuser_1),
.c_m_axis_tkeep(c_s_axis_tkeep_1),
.c_m_axis_tvalid(c_s_axis_tvalid_1),
.c_m_axis_tlast(c_s_axis_tlast_1)
);
lookup_engine_top #(
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.C_S_AXIS_TUSER_WIDTH(C_S_AXIS_TUSER_WIDTH),
.STAGE_ID(STAGE_ID),
.PHV_LEN(),
.KEY_LEN(KEY_LEN),
.ACT_LEN(),
.LOOKUP_ID()
) lookup_engine(
.clk(axis_clk),
.rst_n(aresetn),
//output from key extractor
.extract_key(key2lookup_key_r),
.key_valid(key2lookup_key_valid_r),
.phv_valid(key2lookup_phv_valid_r),
.phv_in(key2lookup_phv_r),
.ready_out(lookup2key_ready),
//output to the action engine
.action (lookup2action_action),
.action_valid (lookup2action_action_valid),
.phv_out (lookup2action_phv),
.ready_in (action2lookup_ready),
//
.act_vlan_out (act_vlan_out),
.act_vlan_valid_out (act_vlan_out_valid),
// .act_vlan_ready (act_vlan_ready),
.act_vlan_ready (action2lookup_ready),
//control path
.c_s_axis_tdata(c_s_axis_tdata_1),
.c_s_axis_tuser(c_s_axis_tuser_1),
.c_s_axis_tkeep(c_s_axis_tkeep_1),
.c_s_axis_tvalid(c_s_axis_tvalid_1),
.c_s_axis_tlast(c_s_axis_tlast_1),
.c_m_axis_tdata(c_s_axis_tdata_2),
.c_m_axis_tuser(c_s_axis_tuser_2),
.c_m_axis_tkeep(c_s_axis_tkeep_2),
.c_m_axis_tvalid(c_s_axis_tvalid_2),
.c_m_axis_tlast(c_s_axis_tlast_2)
);
action_engine #(
.STAGE_ID(STAGE_ID),
.C_S_AXIS_DATA_WIDTH(C_S_AXIS_DATA_WIDTH),
.PHV_LEN(),
.ACT_LEN(),
.ACTION_ID()
)action_engine(
.clk(axis_clk),
.rst_n(aresetn),
//signals from lookup to ALUs
.phv_in(lookup2action_phv_r),
.phv_valid_in(lookup2action_action_valid_r),
.action_in(lookup2action_action_r),
.action_valid_in(lookup2action_action_valid_r),
.ready_out(action2lookup_ready),
//signals output from ALUs
.phv_out (phv_out),
.phv_valid_out (phv_out_valid),
.ready_in (stage_ready_in),
.act_vlan_in (act_vlan_out_r),
.act_vlan_valid_in (act_vlan_out_valid_r),
.act_vlan_ready (act_vlan_ready),
// vlan
.vlan_out(vlan_out),
.vlan_out_valid(vlan_valid_out),
.vlan_out_ready(vlan_out_ready),
//control path
.c_s_axis_tdata(c_s_axis_tdata_2),
.c_s_axis_tuser(c_s_axis_tuser_2),
.c_s_axis_tkeep(c_s_axis_tkeep_2),
.c_s_axis_tvalid(c_s_axis_tvalid_2),
.c_s_axis_tlast(c_s_axis_tlast_2),
.c_m_axis_tdata(c_m_axis_tdata),
.c_m_axis_tuser(c_m_axis_tuser),
.c_m_axis_tkeep(c_m_axis_tkeep),
.c_m_axis_tvalid(c_m_axis_tvalid),
.c_m_axis_tlast(c_m_axis_tlast)
);
endmodule
`timescale 1ns / 1ps
module sub_deparser #(
parameter C_PKT_VEC_WIDTH = (6+4+2)*8*8+256,
parameter C_PARSE_ACT_LEN = 6 // only 6 bits are used here
)
(
input clk,
input aresetn,
input parse_act_valid,
input [C_PARSE_ACT_LEN-1:0] parse_act,
input [C_PKT_VEC_WIDTH-1:0] phv_in,
output reg val_out_valid,
output reg [47:0] val_out,
output reg [1:0] val_out_type
);
localparam PHV_2B_START_POS = 0+256;
localparam PHV_4B_START_POS = 16*8+256;
localparam PHV_6B_START_POS = 16*8+32*8+256;
reg val_out_valid_nxt;
reg [47:0] val_out_nxt;
reg [1:0] val_out_type_nxt;
always @(*) begin
val_out_valid_nxt = 0;
val_out_nxt = val_out;
val_out_type_nxt = val_out_type;
if (parse_act_valid) begin
val_out_valid_nxt = 1;
case({parse_act[5:4], parse_act[0]})
// 2B
3'b011: begin
val_out_type_nxt = 2'b01;
case(parse_act[3:1])
3'd0: val_out_nxt[15:0] = phv_in[PHV_2B_START_POS+16*0 +: 16];
3'd1: val_out_nxt[15:0] = phv_in[PHV_2B_START_POS+16*1 +: 16];
3'd2: val_out_nxt[15:0] = phv_in[PHV_2B_START_POS+16*2 +: 16];
3'd3: val_out_nxt[15:0] = phv_in[PHV_2B_START_POS+16*3 +: 16];
3'd4: val_out_nxt[15:0] = phv_in[PHV_2B_START_POS+16*4 +: 16];
3'd5: val_out_nxt[15:0] = phv_in[PHV_2B_START_POS+16*5 +: 16];
3'd6: val_out_nxt[15:0] = phv_in[PHV_2B_START_POS+16*6 +: 16];
3'd7: val_out_nxt[15:0] = phv_in[PHV_2B_START_POS+16*7 +: 16];
endcase
end
// 4B
3'b101: begin
val_out_type_nxt = 2'b10;
case(parse_act[3:1])
3'd0: val_out_nxt[31:0] = phv_in[PHV_4B_START_POS+32*0 +: 32];
3'd1: val_out_nxt[31:0] = phv_in[PHV_4B_START_POS+32*1 +: 32];
3'd2: val_out_nxt[31:0] = phv_in[PHV_4B_START_POS+32*2 +: 32];
3'd3: val_out_nxt[31:0] = phv_in[PHV_4B_START_POS+32*3 +: 32];
3'd4: val_out_nxt[31:0] = phv_in[PHV_4B_START_POS+32*4 +: 32];
3'd5: val_out_nxt[31:0] = phv_in[PHV_4B_START_POS+32*5 +: 32];
3'd6: val_out_nxt[31:0] = phv_in[PHV_4B_START_POS+32*6 +: 32];
3'd7: val_out_nxt[31:0] = phv_in[PHV_4B_START_POS+32*7 +: 32];
endcase
end
// 6B
3'b111: begin
val_out_type_nxt = 2'b11;
case(parse_act[3:1])
3'd0: val_out_nxt[47:0] = phv_in[PHV_6B_START_POS+48*0 +: 48];
3'd1: val_out_nxt[47:0] = phv_in[PHV_6B_START_POS+48*1 +: 48];
3'd2: val_out_nxt[47:0] = phv_in[PHV_6B_START_POS+48*2 +: 48];
3'd3: val_out_nxt[47:0] = phv_in[PHV_6B_START_POS+48*3 +: 48];
3'd4: val_out_nxt[47:0] = phv_in[PHV_6B_START_POS+48*4 +: 48];
3'd5: val_out_nxt[47:0] = phv_in[PHV_6B_START_POS+48*5 +: 48];
3'd6: val_out_nxt[47:0] = phv_in[PHV_6B_START_POS+48*6 +: 48];
3'd7: val_out_nxt[47:0] = phv_in[PHV_6B_START_POS+48*7 +: 48];
endcase
end
default: begin
val_out_type_nxt = 0;
val_out_nxt = 0;
end
endcase
end
end
always @(posedge clk) begin
if (~aresetn) begin
val_out_valid <= 0;
val_out <= 0;
val_out_type <= 0;
end
else begin
val_out_valid <= val_out_valid_nxt;
val_out <= val_out_nxt;
val_out_type <= val_out_type_nxt;
end
end
endmodule
`timescale 1ns / 1ps
module sub_parser #(
parameter PKTS_HDR_LEN = 1024,
parameter PARSE_ACT_LEN = 16,
parameter VAL_OUT_LEN = 48
)
(
input clk,
input aresetn,
input parse_act_valid,
input [PARSE_ACT_LEN-1:0] parse_act,
input [PKTS_HDR_LEN-1:0] pkts_hdr,
output reg val_out_valid,
output reg [VAL_OUT_LEN-1:0] val_out,
output reg [1:0] val_out_type,
output reg [2:0] val_out_seq
);
reg [VAL_OUT_LEN-1:0] val_out_nxt;
reg val_out_valid_nxt;
reg [1:0] val_out_type_nxt;
reg [2:0] val_out_seq_nxt;
always @(*) begin
val_out_valid_nxt = 0;
val_out_nxt = val_out;
val_out_type_nxt = val_out_type;
val_out_seq_nxt = val_out_seq;
if (parse_act_valid) begin
val_out_valid_nxt = 1;
val_out_seq_nxt = parse_act[3:1];
case({parse_act[5:4], parse_act[0]})
// 2B
3'b011: begin
val_out_type_nxt = 2'b01;
val_out_nxt[15:0] = pkts_hdr[(parse_act[12:6])*8 +: 16];
end
// 4B
3'b101: begin
val_out_type_nxt = 2'b10;
val_out_nxt[31:0] = pkts_hdr[(parse_act[12:6])*8 +: 32];
end
// 6B
3'b111: begin
val_out_type_nxt = 2'b11;
val_out_nxt[47:0] = pkts_hdr[(parse_act[12:6])*8 +: 48];
end
default: begin
val_out_type_nxt = 0;
val_out_nxt = 0;
end
endcase
end
end
always @(posedge clk) begin
if (~aresetn) begin
val_out_valid <= 0;
val_out <= 0;
val_out_type <= 0;
val_out_seq <= 0;
end
else begin
val_out_valid <= val_out_valid_nxt;
val_out <= val_out_nxt;
val_out_type <= val_out_type_nxt;
val_out_seq <= val_out_seq_nxt;
end
end
endmodule
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment