Skip to content

Instantly share code, notes, and snippets.

@upa
Created May 30, 2016 17:00
Show Gist options
  • Save upa/9e5d580aec67d3258c308535b1868b9a to your computer and use it in GitHub Desktop.
Save upa/9e5d580aec67d3258c308535b1868b9a to your computer and use it in GitHub Desktop.
// fthash.v
// embedded sum of src ip and first half of dst ip to src MAC 8 bit
module one_port #(
// Master AXI Stream Data width
parameter C_M_AXIS_DATA_WIDTH=256,
parameter C_M_AXIS_TUSER_WIDTH=128,
parameter C_S_AXIS_DATA_WIDTH=256,
parameter C_S_AXIS_TUSER_WIDTH=128,
parameter SRC_PORT_POS=16,
parameter DST_PORT_POS=24
) (
// Global ports
input axis_aclk,
input axis_resetn,
// Master Stream Ports (Output)
output reg [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_tdata,
output reg [(C_M_AXIS_DATA_WIDTH / 8) - 1:0] m_axis_tkeep,
output reg [C_M_AXIS_TUSER_WIDTH - 1:0] m_axis_tuser,
output reg m_axis_tvalid,
output reg m_axis_tlast,
input wire m_axis_tready,
// Slave Stream Port (Input)
input wire [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_tdata,
input wire [(C_S_AXIS_DATA_WIDTH / 8) - 1:0] s_axis_tkeep,
input wire [C_S_AXIS_TUSER_WIDTH - 1:0] s_axis_tuser,
input wire s_axis_tvalid,
input wire s_axis_tlast,
output wire s_axis_tready
);
wire [C_M_AXIS_TUSER_WIDTH-1:0] tuser_fifo;
wire [C_M_AXIS_DATA_WIDTH-1:0] tdata_fifo;
wire [(C_M_AXIS_DATA_WIDTH / 8) - 1:0] tkeep_fifo;
wire tlast_fifo;
reg [C_M_AXIS_TUSER_WIDTH-1:0] tuser_buf0, tuser_buf1;
reg [C_M_AXIS_DATA_WIDTH-1:0] tdata_buf0, tdata_buf1;
reg [(C_M_AXIS_DATA_WIDTH / 8) - 1:0] tkeep_buf0, tkeep_buf1;
reg tlast_buf0, tlast_buf1;
reg [C_M_AXIS_TUSER_WIDTH-1:0] tuser_fifo_next, tuser_buf0_next, tuser_buf1_next;
reg [C_M_AXIS_DATA_WIDTH-1:0] tdata_fifo_next, tdata_buf0_next, tdata_buf1_next;
reg [(C_M_AXIS_DATA_WIDTH / 8) - 1:0] tkeep_fifo_next, tkeep_buf0_next, tkeep_buf1_next;
reg tlast_fifo_next, tlast_buf0_next, tlast_buf1_next;
wire nearly_full_recvfifo;
wire empty_recvfifo;
wire rd_en_recvfifo;
fallthrough_small_fifo #(
.WIDTH(C_S_AXIS_DATA_WIDTH + C_S_AXIS_DATA_WIDTH/8 + C_S_AXIS_TUSER_WIDTH + 1),
.MAX_DEPTH_BITS (4)
) recv_fifo (
.din ({s_axis_tlast, s_axis_tuser, s_axis_tkeep, s_axis_tdata}),
.dout ({tlast_fifo, tuser_fifo, tkeep_fifo, tdata_fifo}),
.wr_en (s_axis_tvalid && ~nearly_full_recvfifo),
.rd_en (rd_en_recvfifo),
.nearly_full (nearly_full_recvfifo),
.prog_full (),
.empty (empty_recvfifo),
.reset (~axis_resetn),
.clk (axis_aclk)
);
/*
* FSM state machine
*/
localparam DATA0 = 2'd0,
DATA1 = 2'd1,
DATA2 = 2'd2,
IN_PACKET = 2'd3;
reg [1:0] state;
reg [1:0] state_next;
assign s_axis_tready = !nearly_full_recvfifo;
assign rd_en_recvfifo = !empty_recvfifo && m_axis_tready;
// (state == DATA0 || state == DATA1 ||
// state == DATA2 || state == IN_PACKET);
// In DATA0
localparam SRCMAC_POS = 48;
localparam ETHTYPE_POS = 96;
localparam IPPROTO_POS = 184;
// In DATA1
localparam SRCIP_POS = 208;
localparam DSTIP_POS = 240;
localparam DSTIP_POS_SECOND = 0;
// In DATA2
localparam SRCPORT_POS = 16;
localparam DSTPORT_POS = 32;
// Triger Parameter
localparam ETHTYPE_IP = 16'h0008;
localparam IPPROTO_UDP = 8'h11;
localparam IPPROTO_TCP = 8'h06;
assign trig_fthash =
(tdata_fifo_next[ETHTYPE_POS+15:ETHTYPE_POS] == ETHTYPE_IP) &&
(tdata_fifo_next[IPPROTO_POS+7:IPPROTO_POS] == IPPROTO_UDP ||
tdata_fifo_next[IPPROTO_POS+7:IPPROTO_POS] == IPPROTO_TCP);
wire [15:0] debug_eth = tdata_buf0[ETHTYPE_POS+15:ETHTYPE_POS];
wire [7:0] debug_ip = tdata_buf0[IPPROTO_POS+7:IPPROTO_POS];
// trig_fthash means IPv4 TCP or UDP packet
always @ (*) begin
state_next = state;
case (state)
DATA0: begin
m_axis_tvalid = 0;
if (rd_en_recvfifo) begin
tuser_fifo_next = tuser_fifo;
tdata_fifo_next = tdata_fifo;
tkeep_fifo_next = tkeep_fifo;
tlast_fifo_next = tlast_fifo;
tuser_buf0_next = tuser_buf0;
tdata_buf0_next = tdata_buf0;
tkeep_buf0_next = tkeep_buf0;
tlast_buf0_next = tlast_buf0;
tuser_buf1_next = tuser_buf1;
tdata_buf1_next = tdata_buf1;
tkeep_buf1_next = tkeep_buf1;
tlast_buf1_next = tlast_buf1;
state_next = DATA1;
end
end
DATA1: begin
m_axis_tvalid = 0;
if (rd_en_recvfifo) begin
tuser_fifo_next = tuser_fifo;
tdata_fifo_next = tdata_fifo;
tkeep_fifo_next = tkeep_fifo;
tlast_fifo_next = tlast_fifo;
tuser_buf0_next = tuser_buf0;
tdata_buf0_next = tdata_buf0;
tkeep_buf0_next = tkeep_buf0;
tlast_buf0_next = tlast_buf0;
tuser_buf1_next = tuser_buf1;
tdata_buf1_next = tdata_buf1;
tkeep_buf1_next = tkeep_buf1;
tlast_buf1_next = tlast_buf1;
state_next = DATA2;
end
end
DATA2: begin
m_axis_tvalid = 0;
if (rd_en_recvfifo) begin
tuser_fifo_next = tuser_fifo;
tdata_fifo_next = tdata_fifo;
tkeep_fifo_next = tkeep_fifo;
tlast_fifo_next = tlast_fifo;
tuser_buf0_next = tuser_buf0;
tdata_buf0_next = tdata_buf0;
tkeep_buf0_next = tkeep_buf0;
tlast_buf0_next = tlast_buf0;
tuser_buf1_next = tuser_buf1;
tdata_buf1_next = tdata_buf1;
tkeep_buf1_next = tkeep_buf1;
tlast_buf1_next = tlast_buf1;
//if (m_axis_tready)
// m_axis_tvalid = 1;
if (trig_fthash) begin
tdata_buf1_next[SRCMAC_POS+07:SRCMAC_POS+00] = 8'h52;
tdata_buf1_next[SRCMAC_POS+15:SRCMAC_POS+08] = 8'h54;
tdata_buf1_next[SRCMAC_POS+23:SRCMAC_POS+16] = 8'h5e;
tdata_buf1_next[SRCMAC_POS+31:SRCMAC_POS+24] = 8'hBE;
tdata_buf1_next[SRCMAC_POS+39:SRCMAC_POS+32] = 8'hEF;
tdata_buf1_next[SRCMAC_POS+47:SRCMAC_POS+40] =
tdata_buf0_next[SRCIP_POS+07:SRCIP_POS+00] ^
tdata_buf0_next[SRCIP_POS+23:SRCIP_POS+16] ^
tdata_buf0_next[SRCIP_POS+31:SRCIP_POS+24] ^
tdata_buf0_next[DSTIP_POS+07:DSTIP_POS+00] ^
tdata_buf0_next[DSTIP_POS+15:DSTIP_POS+08] ^
tdata_fifo_next[DSTIP_POS_SECOND+07:DSTIP_POS_SECOND+00] ^
tdata_fifo_next[DSTIP_POS_SECOND+15:DSTIP_POS_SECOND+08] ^
tdata_fifo_next[SRCPORT_POS+07:SRCPORT_POS+00] ^
tdata_fifo_next[SRCPORT_POS+15:SRCPORT_POS+08] ^
tdata_fifo_next[DSTPORT_POS+07:DSTPORT_POS+00] ^
tdata_fifo_next[DSTPORT_POS+15:DSTPORT_POS+08];
end
end
if (m_axis_tready) begin
state_next = IN_PACKET;
end
end
IN_PACKET: begin
m_axis_tvalid = 0;
if (m_axis_tready) begin
m_axis_tvalid = 1;
tuser_fifo_next = tuser_fifo;
tdata_fifo_next = tdata_fifo;
tkeep_fifo_next = tkeep_fifo;
tlast_fifo_next = tlast_fifo;
tuser_buf0_next = tuser_buf0;
tdata_buf0_next = tdata_buf0;
tkeep_buf0_next = tkeep_buf0;
tlast_buf0_next = tlast_buf0;
tuser_buf1_next = tuser_buf1;
tdata_buf1_next = tdata_buf1;
tkeep_buf1_next = tkeep_buf1;
tlast_buf1_next = tlast_buf1;
end
if(m_axis_tlast & m_axis_tvalid & m_axis_tready) begin
state_next = DATA0;
end
end
endcase
end
always @(posedge axis_aclk) begin
if(~axis_resetn) begin
state <= DATA0;
tuser_buf0 <= 0;
tdata_buf0 <= 0;
tkeep_buf0 <= 0;
tlast_buf0 <= 0;
tuser_buf1 <= 0;
tdata_buf1 <= 0;
tkeep_buf1 <= 0;
tlast_buf1 <= 0;
m_axis_tuser <= 0;
m_axis_tdata <= 0;
m_axis_tkeep <= 0;
m_axis_tlast <= 0;
end else begin
state <= state_next;
if (rd_en_recvfifo) begin
tuser_buf0 <= tuser_fifo_next;
tdata_buf0 <= tdata_fifo_next;
tkeep_buf0 <= tkeep_fifo_next;
tlast_buf0 <= tlast_fifo_next;
tuser_buf1 <= tuser_buf0_next;
tdata_buf1 <= tdata_buf0_next;
tkeep_buf1 <= tkeep_buf0_next;
tlast_buf1 <= tlast_buf0_next;
m_axis_tuser <= tuser_buf1_next;
m_axis_tdata <= tdata_buf1_next;
m_axis_tkeep <= tkeep_buf1_next;
m_axis_tlast <= tlast_buf1_next;
end
end
end
endmodule
`timescale 1ns/1ps
module tb();
localparam FREQ = 20;
reg clk;
initial clk = 1'b0;
always #(FREQ/2) clk <= ~clk;
reg rstn;
initial rstn = 1'b0;
reg [255:0] tdata;
reg tlast;
wire tready;
reg tvalid = 0;
reg m_tready;
reg [3:0] random = 0;
integer i;
//wire [255:0] data_0 = 256'h0101A8C066554433221101000506070801020608665544332211FFFFFFFFFFFF;
//wire [255:0] data_1 = 256'h000000000000000000000000000000000000000000006401A8C0000000000000;
//
// DSTMAC SRCMAC TYPE IP Parameters SRCIP DSTIP
// 256'h_001111000001_001111000002_0080_45000054b4be00004001b4fb_ac100001_ac10
//
// // DSTIP ICMP ECHO REQUEST Header and Body
// 256'h_0002_0800f9a72a77000c5746e7b4000aa9cc08090a0b0c0d0e0f1011121314151
//
// // ICMP Echo---
// 256'h_61718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536
// 256'h_37000000000000000000000000000000000000000000000000000000000000000
wire [255:0] data_upa_0 = 256'h10ac010010acfbb411400000beb4540000450008020000111100010000111100;
//001111000001001111000002000845000054b4be00004001b4fbac100001ac10;
wire [255:0] data_upa_1 = 256'h1514131211100f0e0d0c0b0a0908cca90a00b4e746570c00772aa7f900080200;
//00020800f9a72a77000c5746e7b4000aa9cc08090a0b0c0d0e0f101112131415;
wire [255:0] data_upa_2 = 256'h3534333231302f2e2d2c2b2a292827262524232221201f1e1d1c1b1a19181716;
//161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435;
wire [255:0] data_upa_3 = 256'h0000000000000000000000000000000000000000000000000000000000003736;
//3637000000000000000000000000000000000000000000000000000000000000;
localparam IDLE = 0;
localparam DATA_0 = 1;
localparam DATA_1 = 2;
localparam DATA_2 = 3;
localparam DATA_3 = 4;
localparam DEAD = 5;
localparam STOP_0 = 6;
localparam STOP_1 = 7;
localparam STOP_2 = 8;
localparam STOP_3 = 9;
localparam STOP_4 = 11;
localparam STOP_5 = 12;
localparam STOP_6 = 13;
localparam STOP_7 = 14;
reg [6:0] state, state_next;
reg [7:0] counter, counter_next;
always @(*) begin
state_next = state;
tdata = 256'b0;
tlast = 1'b0;
counter_next = counter;
case(state)
IDLE : begin
tdata = 0;
tvalid = 0;
state_next = DATA_0;
m_tready = 0;
end
DATA_0: begin
tdata = data_upa_0;
tvalid = 1;
m_tready = 1;
if(tready) begin
state_next = DATA_1;
end
end
DATA_1: begin
tdata = data_upa_1;
m_tready = 1;
if(tready) begin
state_next = DATA_2;
end
end
DATA_2: begin
tdata = data_upa_2;
if(tready) begin
state_next = DATA_3;
end
end
DATA_3: begin
tdata = data_upa_3;
tlast = 1;
if(tready) begin
state_next = STOP_1;
end
end
STOP_1: begin
tdata = 0;
m_tready = 1;
state_next = STOP_2;
end
STOP_2: begin
tdata = 0;
m_tready = 0;
state_next = STOP_3;
end
STOP_3: begin
tdata = 0;
m_tready = 1;
state_next = STOP_4;
end
STOP_4: begin
tdata = 0;
m_tready = 1;
state_next = STOP_5;
end
STOP_5: begin
tdata = 0;
m_tready = 1;
state_next = STOP_6;
end
STOP_6: begin
tdata = 0;
m_tready = 1;
state_next = DEAD;
end
STOP_3: begin
tdata = 0;
m_tready = 1;
state_next = DEAD;
end
DEAD: begin
tlast = 1'b0;
tvalid = 0;
end
endcase
end
always @(posedge clk) begin
if(~rstn) begin
state <= IDLE;
counter <= 8'b0;
end else begin
state <= state_next;
counter <= counter_next;
end
end
one_port inst_u (
// Global ports
.axis_aclk(clk),
.axis_resetn(rstn),
// Master Stream Ports (Output)
.m_axis_tdata(),
.m_axis_tkeep(),
.m_axis_tuser(),
.m_axis_tvalid(),
.m_axis_tlast(),
.m_axis_tready(m_tready),
// Slave Stream Port (Input)
.s_axis_tdata(tdata),
.s_axis_tkeep(32'hFFFF_FFFF),
.s_axis_tuser(128'h0004AAAA),
.s_axis_tvalid(tvalid),
.s_axis_tlast(tlast),
.s_axis_tready(tready)
);
task waitclk;
begin
#FREQ;
end
endtask
initial begin
$dumpfile("dump.vcd");
$dumpvars(0, tb);
rstn = 1'b0;
waitclk;
waitclk;
waitclk;
waitclk;
rstn = 1'b1;
#3000;
$finish();
end
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment