dakies/OSS_Verilog huggingface dataset:
module add2_and_clip
  #(parameter WIDTH=16)
    (input [WIDTH-1:0] in1,
     input [WIDTH-1:0] in2,
     output [WIDTH-1:0] sum);

   wire [WIDTH:0] 	sum_int = {in1[WIDTH-1],in1} + {in2[WIDTH-1],in2};
   clip #(.bits_in(WIDTH+1),.bits_out(WIDTH)) clip
     (.in(sum_int),.out(sum));
   
endmodule // add2_and_clip
module cic_strober
  #(parameter WIDTH=8)
    ( input clock,
      input reset,
      input enable,
      input [WIDTH-1:0] rate, // Rate should EQUAL to your desired divide ratio, no more -1 BS
      input strobe_fast,
      output wire strobe_slow );
   
   reg [WIDTH-1:0] counter;
   wire      now = (counter==1);
   assign    strobe_slow = now && enable && strobe_fast;
   
   always @(posedge clock)
     if(reset)
       counter <= 0; 
     else if (~enable)
       counter <= rate;
     else if(strobe_fast)
       if(now)
	 counter <= rate;
       else 
	 counter <= counter - 1;
   
endmodule // cic_strober
module cic_dec_shifter(rate,signal_in,signal_out);
   parameter bw = 16;
   parameter maxbitgain = 28;

   input [7:0] rate;
   input       wire [bw+maxbitgain-1:0] signal_in;
   output      reg [bw-1:0] signal_out;

   function [4:0] bitgain;
      input [7:0] rate;
      case(rate)
	// Exact Cases -- N*log2(rate)
	8'd1 : bitgain = 0;
	8'd2 : bitgain = 4;
	8'd4 : bitgain = 8;
	8'd8 : bitgain = 12;
	8'd16 : bitgain = 16;
	8'd32 : bitgain = 20;
	8'd64 : bitgain = 24;
	8'd128 : bitgain = 28;
	
	// Nearest without overflow -- ceil(N*log2(rate))
	8'd3 : bitgain = 7;
	8'd5 : bitgain = 10;
	8'd6 : bitgain = 11;
	8'd7 : bitgain = 12;
	8'd9 : bitgain = 13;
	8'd10,8'd11 : bitgain = 14;
	8'd12,8'd13 : bitgain = 15;
	8'd14,8'd15 : bitgain = 16;
	8'd17,8'd18,8'd19 : bitgain = 17;
	8'd20,8'd21,8'd22 : bitgain = 18;
	8'd23,8'd24,8'd25,8'd26 : bitgain = 19;
	8'd27,8'd28,8'd29,8'd30,8'd31 : bitgain = 20;
	8'd33,8'd34,8'd35,8'd36,8'd37,8'd38 : bitgain = 21;
	8'd39,8'd40,8'd41,8'd42,8'd43,8'd44,8'd45 : bitgain = 22;
	8'd46,8'd47,8'd48,8'd49,8'd50,8'd51,8'd52,8'd53 : bitgain = 23;
	8'd54,8'd55,8'd56,8'd57,8'd58,8'd59,8'd60,8'd61,8'd62,8'd63 : bitgain = 24;
	8'd65,8'd66,8'd67,8'd68,8'd69,8'd70,8'd71,8'd72,8'd73,8'd74,8'd75,8'd76 : bitgain = 25;
	8'd77,8'd78,8'd79,8'd80,8'd81,8'd82,8'd83,8'd84,8'd85,8'd86,8'd87,8'd88,8'd89,8'd90 : bitgain = 26;
	8'd91,8'd92,8'd93,8'd94,8'd95,8'd96,8'd97,8'd98,8'd99,8'd100,8'd101,8'd102,8'd103,8'd104,8'd105,8'd106,8'd107 : bitgain = 27;
	default : bitgain = 28;
      endcase // case(rate)
   endfunction // bitgain
   
   wire [4:0] 	  shift = bitgain(rate);
   
   // We should be able to do this, but can't ....
   // assign 	  signal_out = signal_in[shift+bw-1:shift];
   
   always @*
     case(shift)
       5'd0  : signal_out = signal_in[0+bw-1:0];
       5'd4  : signal_out = signal_in[4+bw-1:4];
       5'd7  : signal_out = signal_in[7+bw-1:7];
       5'd8  : signal_out = signal_in[8+bw-1:8];
       5'd10 : signal_out = signal_in[10+bw-1:10];
       5'd11 : signal_out = signal_in[11+bw-1:11];
       5'd12 : signal_out = signal_in[12+bw-1:12];
       5'd13 : signal_out = signal_in[13+bw-1:13];
       5'd14 : signal_out = signal_in[14+bw-1:14];
       5'd15 : signal_out = signal_in[15+bw-1:15];
       5'd16 : signal_out = signal_in[16+bw-1:16];
       5'd17 : signal_out = signal_in[17+bw-1:17];
       5'd18 : signal_out = signal_in[18+bw-1:18];
       5'd19 : signal_out = signal_in[19+bw-1:19];
       5'd20 : signal_out = signal_in[20+bw-1:20];
       5'd21 : signal_out = signal_in[21+bw-1:21];
       5'd22 : signal_out = signal_in[22+bw-1:22];
       5'd23 : signal_out = signal_in[23+bw-1:23];
       5'd24 : signal_out = signal_in[24+bw-1:24];
       5'd25 : signal_out = signal_in[25+bw-1:25];
       5'd26 : signal_out = signal_in[26+bw-1:26];
       5'd27 : signal_out = signal_in[27+bw-1:27];
       5'd28 : signal_out = signal_in[28+bw-1:28];
       
       default : signal_out = signal_in[28+bw-1:28];
     endcase // case(shift)

endmodule // cic_dec_shifter
module round_reg
  #(parameter bits_in=0,
    parameter bits_out=0)
    (input clk,
     input [bits_in-1:0] in,
     output reg [bits_out-1:0] out,
     output reg [bits_in-bits_out:0] err);

   wire [bits_out-1:0] temp;
   wire [bits_in-bits_out:0] err_temp;
   
   round #(.bits_in(bits_in),.bits_out(bits_out)) round (.in(in),.out(temp), .err(err_temp));
   
   always @(posedge clk)
     out <= temp;

   always @(posedge clk)
     err <= err_temp;
   
endmodule // round_reg
module cic_interp
  #(parameter bw = 16, parameter N = 4, parameter log2_of_max_rate = 7)
    (input clock,
     input reset,
     input enable,
     input [7:0] rate,
     input strobe_in,
     input strobe_out,
     input [bw-1:0] signal_in,
     output reg [bw-1:0] signal_out);
   
   integer 	     i;
   localparam 	     maxbitgain = (N-1)*log2_of_max_rate;

   wire [bw+maxbitgain-1:0] signal_in_ext;
   reg [bw+maxbitgain-1:0]  integrator [0:N-1];
   reg [bw+maxbitgain-1:0]  differentiator [0:N-1];
   reg [bw+maxbitgain-1:0]  pipeline [0:N-1];
   
   sign_extend #(bw,bw+maxbitgain) 
     ext_input (.in(signal_in),.out(signal_in_ext));
   
   //FIXME Note that this section has pipe and diff reversed
   // It still works, but is confusing
   always @(posedge clock)
     if(reset | ~enable)
       for(i=0;i<N;i=i+1)
	 integrator[i] <= 0;
     else if (enable & strobe_out)
       begin
	  if(strobe_in)
	    integrator[0] <= integrator[0] + pipeline[N-1];
	  for(i=1;i<N;i=i+1)
	    integrator[i] <= integrator[i] + integrator[i-1];
       end
   
   always @(posedge clock)
     if(reset | ~enable)
       begin
	  for(i=0;i<N;i=i+1)
	    begin
	       differentiator[i] <= 0;
	       pipeline[i] <= 0;
 	    end
       end
     else if (enable && strobe_in)
       begin
	  differentiator[0] <= signal_in_ext;
	  pipeline[0] <= signal_in_ext - differentiator[0];
	  for(i=1;i<N;i=i+1)
	    begin
	       differentiator[i] <= pipeline[i-1];
	       pipeline[i] <= pipeline[i-1] - differentiator[i];
	    end
       end

   wire [bw-1:0] signal_out_unreg;
   cic_int_shifter #(bw)
     cic_int_shifter(rate,integrator[N-1],signal_out_unreg);
   
   always @(posedge clock)
     signal_out <= signal_out_unreg;
   
endmodule // cic_interp
module acc
  #(parameter IWIDTH=16, OWIDTH=30)
    (input clk,
     input clear,
     input acc,
     input [IWIDTH-1:0] in,
     output reg [OWIDTH-1:0] out);

   wire [OWIDTH-1:0] in_signext;
   sign_extend #(.bits_in(IWIDTH),.bits_out(OWIDTH)) 
     acc_signext (.in(in),.out(in_signext));
   
   //  CLEAR & ~ACC  -->  clears the accumulator
   //  CLEAR & ACC -->    loads the accumulator
   //  ~CLEAR & ACC -->   accumulates
   //  ~CLEAR & ~ACC -->  hold
   
   wire [OWIDTH-1:0] addend1 = clear ? 0 : out;
   wire [OWIDTH-1:0] addend2 = ~acc ? 0 : in_signext;
   wire [OWIDTH-1:0] sum_int = addend1 + addend2;

   always @(posedge clk)
     out <= sum_int;
   
endmodule // acc
module axis_port_terminator #(
  parameter DATA_W = 64
) (
  // Clocks and resets
  input  wire               clk,
  input  wire               reset,
  // Input ports
  input  wire [DATA_W-1:0]  s_axis_tdata,   // Input data
  input  wire               s_axis_tlast,   // Input EOP (last)
  input  wire               s_axis_tvalid,  // Input valid
  output wire               s_axis_tready,  // Input ready
  // Output ports
  output wire [DATA_W-1:0]  m_axis_tdata,   // Output data
  output wire               m_axis_tlast,   // Output EOP (last) 
  output wire               m_axis_tvalid,  // Output valid
  input  wire               m_axis_tready,  // Output ready
  // Metrics
  output reg  [15:0]        pkts_dropped
);

  assign s_axis_tready  = 1'b1;
  assign m_axis_tdata   = {DATA_W{1'b0}};
  assign m_axis_tlast   = 1'b0;
  assign m_axis_tvalid  = 1'b0;

  always @(posedge clk) begin
    if (reset) begin
      pkts_dropped <= 'd0;
    end else if (s_axis_tvalid & s_axis_tlast & s_axis_tready) begin
      pkts_dropped <= pkts_dropped + 'd1;
    end
  end

endmodule
module axi_fifo_short
  #(parameter WIDTH=32)
   (
    input clk, 
    input reset, 
    input clear,
    input [WIDTH-1:0] i_tdata,
    input i_tvalid,
    output i_tready,
    output [WIDTH-1:0] o_tdata,
    output o_tvalid,
    input o_tready,
    
    output reg [5:0] space,
    output reg [5:0] occupied
    );

   reg full = 1'b0, empty = 1'b1;
   wire write 	     = i_tvalid & i_tready;
   wire read 	     = o_tready & o_tvalid;

   assign i_tready  = ~full;
   assign o_tvalid  = ~empty;
   
   reg [4:0] 	  a;
   genvar 	  i; 
   
   generate
      for (i=0;i<WIDTH;i=i+1)
	begin : gen_srlc32e
	   SRLC32E
	     srlc32e(.Q(o_tdata[i]), .Q31(),
		     .A(a), //.A0(a[0]),.A1(a[1]),.A2(a[2]),.A3(a[3]),.A4(a[4]),
		    .CE(write),.CLK(clk),.D(i_tdata[i]));
	end
   endgenerate
   
   always @(posedge clk)
     if(reset)
       begin
	  a <= 0;
	  empty <= 1;
	  full <= 0;
       end
     else if(clear)
       begin
	  a <= 0;
	  empty <= 1;
	  full<= 0;
       end
     else if(read & ~write)
       begin
	  full <= 0;
	  if(a==0)
	    empty <= 1;
	  else
	    a <= a - 1;
       end
     else if(write & ~read)
       begin
	  empty <= 0;
	  if(~empty)
	    a <= a + 1;
	  if(a == 30)
	    full <= 1;
       end

   // NOTE will fail if you write into a full fifo or read from an empty one

   //////////////////////////////////////////////////////////////
   // space and occupied are used for diagnostics, not 
   // guaranteed correct
   
   //assign space = full ? 0 : empty ? 16 : 15-a;
   //assign occupied = empty ? 0 : full ? 16 : a+1;

   always @(posedge clk)
     if(reset)
       space <= 6'd32;
     else if(clear)
       space <= 6'd32;
     else if(read & ~write)
       space <= space + 6'd1;
     else if(write & ~read)
       space <= space - 6'd1;
   
   always @(posedge clk)
     if(reset)
       occupied <= 6'd0;
     else if(clear)
       occupied <= 6'd0;
     else if(read & ~write)
       occupied <= occupied - 6'd1;
     else if(write & ~read)
       occupied <= occupied + 6'd1;
      
endmodule // axi_fifo_short
module shortfifo
  #(parameter WIDTH=32)
    (input clk, input rst,
     input [WIDTH-1:0] datain,
     output [WIDTH-1:0] dataout,
     input read,
     input write,
     input clear,
     output reg full,
     output reg empty,
     output reg [4:0] space,
     output reg [4:0] occupied);
   
   reg [3:0] 	  a;
   genvar 	  i;
   
   generate
      for (i=0;i<WIDTH;i=i+1)
	begin : gen_srl16
	   SRL16E
	     srl16e(.Q(dataout[i]),
		    .A0(a[0]),.A1(a[1]),.A2(a[2]),.A3(a[3]),
		    .CE(write),.CLK(clk),.D(datain[i]));
	end
   endgenerate
   
   always @(posedge clk)
     if(rst)
       begin
	  a <= 0;
	  empty <= 1;
	  full <= 0;
       end
     else if(clear)
       begin
	  a <= 0;
	  empty <= 1;
	  full<= 0;
       end
     else if(read & ~write)
       begin
	  full <= 0;
	  if(a==0)
	    empty <= 1;
	  else
	    a <= a - 1;
       end
     else if(write & ~read)
       begin
	  empty <= 0;
	  if(~empty)
	    a <= a + 1;
	  if(a == 14)
	    full <= 1;
       end

   // NOTE will fail if you write into a full fifo or read from an empty one

   //////////////////////////////////////////////////////////////
   // space and occupied are used for diagnostics, not 
   // guaranteed correct
   
   //assign space = full ? 0 : empty ? 16 : 15-a;
   //assign occupied = empty ? 0 : full ? 16 : a+1;

   always @(posedge clk)
     if(rst)
       space <= 16;
     else if(clear)
       space <= 16;
     else if(read & ~write)
       space <= space + 1;
     else if(write & ~read)
       space <= space - 1;
   
   always @(posedge clk)
     if(rst)
       occupied <= 0;
     else if(clear)
       occupied <= 0;
     else if(read & ~write)
       occupied <= occupied - 1;
     else if(write & ~read)
       occupied <= occupied + 1;
      
endmodule // shortfifo
module axi_fifo64_to_fifo32
  (input clk, input reset, input clear,
   input [63:0] i_tdata, input [2:0] i_tuser, input i_tlast, input i_tvalid, output i_tready,
   output [31:0] o_tdata, output [1:0] o_tuser, output o_tlast, output o_tvalid, input o_tready
   );

   wire 	 short_last = i_tlast & ((i_tuser == 3'd1) | (i_tuser == 3'd2) | (i_tuser == 3'd3) | (i_tuser == 3'd4));
   
   reg 		 state;
   always @(posedge clk)
     if(reset | clear)
       state <= 1'b0;
     else
       if(i_tvalid & o_tready)
	 case(state)
	   1'b0 :
	     if(~short_last)
	       state <= 1'b1;
	   1'b1 :
	     state <= 1'b0;
	 endcase // case (state)
   
   assign o_tdata = (state == 0) ? i_tdata[63:32] : i_tdata[31:0];
   assign o_tuser = o_tlast ? i_tuser[1:0] : 2'd0;
   assign o_tlast = i_tlast & ((state == 1'b1) | short_last);

   assign o_tvalid = i_tvalid;
   assign i_tready = o_tready & ((state == 1'b1) | short_last);
   		    
endmodule // axi_fifo64_to_fifo32
module axi_fifo_flop2 #(
  parameter WIDTH = 32
)(
  input clk,
  input reset,
  input clear,
  input [WIDTH-1:0] i_tdata,
  input i_tvalid,
  output i_tready,
  output reg [WIDTH-1:0] o_tdata,
  output reg o_tvalid,
  input o_tready,
  output [1:0] space,
  output [1:0] occupied);

  reg [WIDTH-1:0] i_tdata_temp;
  reg             i_tvalid_temp;

  assign i_tready = ~i_tvalid_temp;

  always @(posedge clk) begin
    if (~o_tvalid | o_tready) begin
      if (i_tvalid_temp) begin
        o_tvalid      <= 1'b1;
        o_tdata       <= i_tdata_temp;
      end else begin
        o_tvalid      <= i_tvalid;
        o_tdata       <= i_tdata;
      end
      i_tvalid_temp   <= 1'b0;
    end else begin
      if (~i_tvalid_temp) begin
        i_tvalid_temp <= i_tvalid;
        i_tdata_temp  <= i_tdata;
      end
    end
    if (reset | clear) begin
      o_tvalid      <= 1'b0;
      i_tvalid_temp <= 1'b0;
    end
  end

  assign occupied = i_tvalid_temp + o_tvalid;
  assign space    = 2 - occupied;

endmodule
module axi_fifo32_to_fifo16
  (input clk, input reset, input clear,
   input [31:0] i_tdata, input [2:0] i_tuser, input i_tlast, input i_tvalid, output i_tready,
   output [15:0] o_tdata, output [1:0] o_tuser, output o_tlast, output o_tvalid, input o_tready
   );

   wire 	 short_last = i_tlast & ((i_tuser == 3'd1) | (i_tuser == 3'd2) | (i_tuser == 3'd3) | (i_tuser == 3'd4));
   
   reg 		 state;
   always @(posedge clk)
     if(reset | clear)
       state <= 1'b0;
     else
       if(i_tvalid & o_tready)
	 case(state)
	   1'b0 :
	     if(~short_last)
	       state <= 1'b1;
	   1'b1 :
	     state <= 1'b0;
	 endcase // case (state)
   
   assign o_tdata = (state == 0) ? i_tdata[31:16] : i_tdata[15:0];
   assign o_tuser = o_tlast ? i_tuser[1:0] : 2'd0;
   assign o_tlast = i_tlast & ((state == 1'b1) | short_last);

   assign o_tvalid = i_tvalid;
   assign i_tready = o_tready & ((state == 1'b1) | short_last);
   		    
endmodule // axi_fifo64_to_fifo32
module axi_demux
  #(parameter WIDTH=64,
    parameter SIZE=4,
    parameter PRE_FIFO_SIZE=0,
    parameter POST_FIFO_SIZE=0)
   (input clk, input reset, input clear,
    output [WIDTH-1:0] header, input [$clog2(SIZE)-1:0] dest,
    input [WIDTH-1:0] i_tdata, input i_tlast, input i_tvalid, output i_tready,
    output [(WIDTH*SIZE)-1:0] o_tdata, output [SIZE-1:0] o_tlast, output [SIZE-1:0] o_tvalid, input [SIZE-1:0] o_tready);

   wire i_tlast_int, i_tready_int, i_tvalid_int;
   wire [WIDTH-1:0] i_tdata_int;
   generate
     if (PRE_FIFO_SIZE == 0) begin
       assign i_tlast_int = i_tlast;
       assign i_tdata_int = i_tdata;
       assign i_tvalid_int = i_tvalid;
       assign i_tready = i_tready_int;
     end else begin
       axi_fifo #(.WIDTH(WIDTH+1),.SIZE(PRE_FIFO_SIZE)) axi_fifo (
         .clk(clk), .reset(reset), .clear(clear),
         .i_tdata({i_tlast,i_tdata}), .i_tvalid(i_tvalid), .i_tready(i_tready),
         .o_tdata({i_tlast_int,i_tdata_int}), .o_tvalid(i_tvalid_int), .o_tready(i_tready_int),
         .space(), .occupied());
     end
   endgenerate

   reg [SIZE-1:0] 	      st;

   assign header = i_tdata_int;

   always @(posedge clk)
     if(reset | clear)
       st <= {SIZE{1'b0}};
     else
       if(st == 0)
	 if(i_tvalid_int)
	   st[dest] <= 1'b1;
	 else
	   ;
       else
	 if(i_tready_int & i_tvalid_int & i_tlast_int)
	   st <= {SIZE{1'b0}};
   
   wire [SIZE-1:0]  o_tlast_int, o_tready_int, o_tvalid_int;
   wire [WIDTH-1:0] o_tdata_int[0:SIZE-1];
   genvar n;
   generate
     if (POST_FIFO_SIZE == 0) begin
       assign o_tdata = {SIZE{i_tdata_int}};
       assign o_tlast = {SIZE{i_tlast_int}};
       assign o_tvalid = {SIZE{i_tvalid_int}} & st;
       assign i_tready_int = |(o_tready & st);
     end else begin
       wire [SIZE-1:0] o_tready_fifo;
       assign i_tready_int = |(o_tready_fifo & st);
       for (n = 0; n < SIZE; n = n + 1) begin
         axi_fifo #(.WIDTH(WIDTH+1),.SIZE(POST_FIFO_SIZE)) axi_fifo (
           .clk(clk), .reset(reset), .clear(clear),
           .i_tdata({i_tlast_int,i_tdata_int}), .i_tvalid(i_tvalid_int & st[n]), .i_tready(o_tready_fifo[n]),
           .o_tdata({o_tlast[n],o_tdata[WIDTH*(n+1)-1:WIDTH*n]}), .o_tvalid(o_tvalid[n]), .o_tready(o_tready[n]),
           .space(), .occupied());
       end
     end
   endgenerate

endmodule // axi_demux
module axi_fifo16_to_fifo32
  (input clk, input reset, input clear,
   input [15:0] i_tdata, input [1:0] i_tuser, input i_tlast, input i_tvalid, output i_tready,
   output [31:0] o_tdata, output [2:0] o_tuser, output o_tlast, output o_tvalid, input o_tready
   );

   reg [15:0] 	 holding;

   reg 		 state;

   always @(posedge clk)
     if(reset | clear)
       state <= 0;
     else
       if(i_tvalid & i_tready)
       case(state)
	 0 : if(~i_tlast) state <= 1'b1;
    	 1 : state <= 1'b0;
	 default : state <= 1'b0;
       endcase // case (state)

   always @(posedge clk)
     if(i_tvalid & i_tready)
       holding <= i_tdata;
   
   assign i_tready = (state == 0 && !i_tlast)? 1'b1 : o_tready;
   assign o_tvalid = (state == 0 && !i_tlast)? 1'b0 : i_tvalid;
   
   assign o_tdata = (state == 0) ? {i_tdata, 16'h0} : { holding, i_tdata };
   assign o_tlast = i_tlast;

   wire [2:0] 	 occ_in = (i_tuser == 0) ? 3'd4 : {1'b0, i_tuser};
   wire [2:0] 	 occ_out = (state == 0) ? occ_in : (occ_in + 3'd4);
   
   assign o_tuser = ~o_tlast ? 3'd0 : occ_out;
   	 
endmodule // axi_fifo32_to_fifo64
module axi_fifo
  #(parameter WIDTH=32, SIZE=5)
   (input clk, input reset, input clear,
    input [WIDTH-1:0] i_tdata,
    input i_tvalid,
    output i_tready,
    output [WIDTH-1:0] o_tdata,
    output o_tvalid,
    input o_tready,
    
    output [15:0] space,
    output [15:0] occupied);
   
   generate
   if(SIZE==0)
   begin
      axi_fifo_flop #(.WIDTH(WIDTH)) fifo_flop
        (.clk(clk), .reset(reset), .clear(clear),
         .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready),
         .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready),
         .space(space[0]), .occupied(occupied[0]));
      assign space[15:1] = 15'd0;
      assign occupied[15:1] = 15'd0;
   end
   else if(SIZE==1)
   begin
      axi_fifo_flop2 #(.WIDTH(WIDTH)) fifo_flop2
        (.clk(clk), .reset(reset), .clear(clear),
         .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready),
         .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready),
         .space(space[1:0]), .occupied(occupied[1:0]));
      assign space[15:2] = 14'd0;
      assign occupied[15:2] = 14'd0;
   end
   else if(SIZE<=5)
   begin
      axi_fifo_short #(.WIDTH(WIDTH)) fifo_short
        (.clk(clk), .reset(reset), .clear(clear),
         .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready),
         .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready),
         .space(space[5:0]), .occupied(occupied[5:0]));
      assign space[15:6] = 10'd0;
      assign occupied[15:6] = 10'd0;
   end
   else
   begin
      axi_fifo_bram #(.WIDTH(WIDTH), .SIZE(SIZE)) fifo_bram
        (.clk(clk), .reset(reset), .clear(clear),
         .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready),
         .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready),
         .space(space), .occupied(occupied));
   end
   endgenerate
      
endmodule // axi_fifo
module axis_strm_monitor #(
  parameter WIDTH         = 64,
  parameter COUNT_W       = 32,
  parameter PKT_LENGTH_EN = 0,
  parameter PKT_CHKSUM_EN = 0,
  parameter PKT_COUNT_EN  = 0,
  parameter XFER_COUNT_EN = 0
)(
  // Clocks and resets
  input  wire               clk,
  input  wire               reset,
  // Stream to monitor      
  input  wire [WIDTH-1:0]   axis_tdata,
  input  wire               axis_tlast,
  input  wire               axis_tvalid,
  input  wire               axis_tready,
  // Packet Stats
  output wire               sop,
  output wire               eop,
  output reg  [15:0]        pkt_length = 16'd0,
  output wire [WIDTH-1:0]   pkt_chksum,
  // Stream Stats
  output reg  [COUNT_W-1:0] pkt_count  = {COUNT_W{1'b0}},
  output reg  [COUNT_W-1:0] xfer_count = {COUNT_W{1'b0}}
);

  //----------------------------
  // Packet specific
  //----------------------------

  reg pkt_head = 1'b1;
  wire xfer = axis_tvalid & axis_tready;

  assign sop = pkt_head & xfer;
  assign eop = xfer & axis_tlast;

  always @(posedge clk) begin
    if (reset) begin
      pkt_head <= 1'b1;
    end else begin
      if (pkt_head) begin
        if (xfer)
          pkt_head <= ~eop;
      end else begin
        if (eop)
          pkt_head <= 1'b0;
      end
    end
  end

  generate if (PKT_LENGTH_EN == 0) begin
    // Count the number of lines (transfers) in a packet
    always @(posedge clk) begin
      if (reset | eop) begin
        pkt_length <= 16'd1;
      end else if (xfer) begin
        pkt_length <= pkt_length + 1'b1;
      end
    end
  end else begin
    // Default packet length is 0
    always @(*) pkt_length <= 16'd0;
  end endgenerate

  generate if (PKT_LENGTH_EN == 0) begin
    // Compute the XOR checksum of the lines in a packet
    reg [WIDTH-1:0] chksum_prev = {WIDTH{1'b0}};
    always @(posedge clk) begin
      if (reset) begin
        chksum_prev <= {WIDTH{1'b0}};
      end else if (xfer) begin
        chksum_prev <= pkt_chksum;
      end
    end
    assign pkt_chksum = chksum_prev ^ axis_tdata;
  end else begin
    // Default checksum is 0
    assign pkt_chksum = {WIDTH{1'b0}};
  end endgenerate

  //----------------------------
  // Stream specific
  //----------------------------

  always @(posedge clk) begin
    if (reset | (PKT_COUNT_EN == 0)) begin
      pkt_count <= {COUNT_W{1'b0}};
    end else if (eop) begin
      pkt_count <= pkt_count + 1'b1;
    end
  end

  always @(posedge clk) begin
    if (reset | (XFER_COUNT_EN == 0)) begin
      xfer_count <= {COUNT_W{1'b0}};
    end else if (xfer) begin
      xfer_count <= xfer_count + 1'b1;
    end
  end

 endmodule
module axis_fifo_monitor #(
  parameter COUNT_W = 32
)(
  // Clocks and resets
  input  wire               clk,
  input  wire               reset,
  // FIFO Input      
  input  wire               i_tlast,
  input  wire               i_tvalid,
  input  wire               i_tready,
  // FIFO Output      
  input  wire               o_tlast,
  input  wire               o_tvalid,
  input  wire               o_tready,
  // FIFO Stats
  output wire               i_sop,
  output wire               i_eop,
  output wire               o_sop,
  output wire               o_eop,
  output wire [COUNT_W-1:0] occupied,
  output wire [COUNT_W-1:0] occupied_pkts
);

  wire [COUNT_W-1:0] i_pkt_count, o_pkt_count;
  wire [COUNT_W-1:0] i_xfer_count, o_xfer_count;

  axis_strm_monitor #(
    .WIDTH(1), .COUNT_W(COUNT_W),
    .PKT_LENGTH_EN(0), .PKT_CHKSUM_EN(0),
    .PKT_COUNT_EN(1), .XFER_COUNT_EN(1)
  ) input_monitor (
    .clk(clk), .reset(reset),
    .axis_tdata(1'b0), .axis_tlast(i_tlast), .axis_tvalid(i_tvalid), .axis_tready(i_tready),
    .sop(i_sop), .eop(i_eop),
    .pkt_length(), .pkt_chksum(),
    .pkt_count(i_pkt_count), .xfer_count(i_xfer_count)
  );

  axis_strm_monitor #(
    .WIDTH(1), .COUNT_W(COUNT_W),
    .PKT_LENGTH_EN(0), .PKT_CHKSUM_EN(0),
    .PKT_COUNT_EN(1), .XFER_COUNT_EN(1)
  ) output_monitor (
    .clk(clk), .reset(reset),
    .axis_tdata(1'b0), .axis_tlast(o_tlast), .axis_tvalid(o_tvalid), .axis_tready(o_tready),
    .sop(o_sop), .eop(o_eop),
    .pkt_length(), .pkt_chksum(),
    .pkt_count(o_pkt_count), .xfer_count(o_xfer_count)
  );

  // Count packets in FIFO.
  // No protection on counter wrap, 
  assign occupied      = (o_xfer_count - i_xfer_count);
  assign occupied_pkts = (o_pkt_count  - i_pkt_count);

 endmodule
module axi_mux8 #(
   parameter PRIO=0,
   parameter WIDTH=64,
   parameter BUFFER=0
) (
   input clk, input reset, input clear,
   input [WIDTH-1:0] i0_tdata, input i0_tlast, input i0_tvalid, output i0_tready,
   input [WIDTH-1:0] i1_tdata, input i1_tlast, input i1_tvalid, output i1_tready,
   input [WIDTH-1:0] i2_tdata, input i2_tlast, input i2_tvalid, output i2_tready,
   input [WIDTH-1:0] i3_tdata, input i3_tlast, input i3_tvalid, output i3_tready,
   input [WIDTH-1:0] i4_tdata, input i4_tlast, input i4_tvalid, output i4_tready,
   input [WIDTH-1:0] i5_tdata, input i5_tlast, input i5_tvalid, output i5_tready,
   input [WIDTH-1:0] i6_tdata, input i6_tlast, input i6_tvalid, output i6_tready,
   input [WIDTH-1:0] i7_tdata, input i7_tlast, input i7_tvalid, output i7_tready,
   output [WIDTH-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready
);

   wire [WIDTH-1:0]  o_tdata_int0, o_tdata_int1;
   wire              o_tlast_int0, o_tlast_int1;
   wire              o_tvalid_int0, o_tvalid_int1;
   wire              o_tready_int0, o_tready_int1;

   axi_mux4 #(.PRIO(PRIO), .WIDTH(WIDTH), .BUFFER(0)) mux4_int0 (
      .clk(clk), .reset(reset), .clear(clear),
      .i0_tdata(i0_tdata), .i0_tlast(i0_tlast), .i0_tvalid(i0_tvalid), .i0_tready(i0_tready),
      .i1_tdata(i1_tdata), .i1_tlast(i1_tlast), .i1_tvalid(i1_tvalid), .i1_tready(i1_tready),
      .i2_tdata(i2_tdata), .i2_tlast(i2_tlast), .i2_tvalid(i2_tvalid), .i2_tready(i2_tready),
      .i3_tdata(i3_tdata), .i3_tlast(i3_tlast), .i3_tvalid(i3_tvalid), .i3_tready(i3_tready),
      .o_tdata(o_tdata_int0), .o_tlast(o_tlast_int0), .o_tvalid(o_tvalid_int0), .o_tready(o_tready_int0)
   );

   axi_mux4 #(.PRIO(PRIO), .WIDTH(WIDTH), .BUFFER(0)) mux4_int1 (
      .clk(clk), .reset(reset), .clear(clear),
      .i0_tdata(i4_tdata), .i0_tlast(i4_tlast), .i0_tvalid(i4_tvalid), .i0_tready(i4_tready),
      .i1_tdata(i5_tdata), .i1_tlast(i5_tlast), .i1_tvalid(i5_tvalid), .i1_tready(i5_tready),
      .i2_tdata(i6_tdata), .i2_tlast(i6_tlast), .i2_tvalid(i6_tvalid), .i2_tready(i6_tready),
      .i3_tdata(i7_tdata), .i3_tlast(i7_tlast), .i3_tvalid(i7_tvalid), .i3_tready(i7_tready),
      .o_tdata(o_tdata_int1), .o_tlast(o_tlast_int1), .o_tvalid(o_tvalid_int1), .o_tready(o_tready_int1)
   );

   axi_mux4 #(.PRIO(PRIO), .WIDTH(WIDTH), .BUFFER(BUFFER)) mux2 (
      .clk(clk), .reset(reset), .clear(clear),
      .i0_tdata(o_tdata_int0), .i0_tlast(o_tlast_int0), .i0_tvalid(o_tvalid_int0), .i0_tready(o_tready_int0),
      .i1_tdata(o_tdata_int1), .i1_tlast(o_tlast_int1), .i1_tvalid(o_tvalid_int1), .i1_tready(o_tready_int1),
      .i2_tdata(0), .i2_tlast(1'b0), .i2_tvalid(1'b0), .i2_tready(),
      .i3_tdata(0), .i3_tlast(1'b0), .i3_tvalid(1'b0), .i3_tready(),
      .o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready)
   );

endmodule // axi_mux8
module axi_fifo_flop
  #(parameter WIDTH=32)
   (input clk,
    input reset,
    input clear,
    input [WIDTH-1:0] i_tdata,
    input i_tvalid,
    output i_tready,
    output reg [WIDTH-1:0] o_tdata = 'd0,
    output reg o_tvalid = 1'b0,
    input o_tready,
    output space,
    output occupied);

   assign i_tready = ~reset & (~o_tvalid | o_tready);

   always @(posedge clk)
     if(reset | clear)
       o_tvalid <= 1'b0;
     else
       o_tvalid <= (i_tready & i_tvalid) | (o_tvalid & ~o_tready);

   always @(posedge clk)
     if(i_tvalid & i_tready)
       o_tdata <= i_tdata;

   // These aren't terribly useful, but include them for consistency
   assign space = i_tready;
   assign occupied = o_tvalid;

endmodule // axi_fifo_flop
module axi_demux4
  #(parameter ACTIVE_CHAN = 4'b1111,  // ACTIVE_CHAN is a map of connected outputs
    parameter WIDTH = 64,
    parameter BUFFER=0)
   (input clk, input reset, input clear,
    output [WIDTH-1:0] header, input [1:0] dest,
    input [WIDTH-1:0] i_tdata, input i_tlast, input i_tvalid, output i_tready,
    output [WIDTH-1:0] o0_tdata, output o0_tlast, output o0_tvalid, input o0_tready,
    output [WIDTH-1:0] o1_tdata, output o1_tlast, output o1_tvalid, input o1_tready,
    output [WIDTH-1:0] o2_tdata, output o2_tlast, output o2_tvalid, input o2_tready,
    output [WIDTH-1:0] o3_tdata, output o3_tlast, output o3_tvalid, input o3_tready);

   wire [WIDTH-1:0]    i_tdata_int;
   wire 	       i_tlast_int, i_tvalid_int, i_tready_int;

   generate
      if(BUFFER == 0)
	begin
	   assign i_tdata_int = i_tdata;
	   assign i_tlast_int = i_tlast;
	   assign i_tvalid_int = i_tvalid;
	   assign i_tready = i_tready_int;
	end
      else
	axi_fifo_flop2 #(.WIDTH(WIDTH+1)) axi_fifo_flop2
	  (.clk(clk), .reset(reset), .clear(clear),
	   .i_tdata({i_tlast,i_tdata}), .i_tvalid(i_tvalid), .i_tready(i_tready),
	   .o_tdata({i_tlast_int,i_tdata_int}), .o_tvalid(i_tvalid_int), .o_tready(i_tready_int),
	   .space(), .occupied());
   endgenerate

   reg [3:0] 	  dm_state;
   localparam DM_IDLE = 4'b0000;
   localparam DM_0    = 4'b0001;
   localparam DM_1    = 4'b0010;
   localparam DM_2    = 4'b0100;
   localparam DM_3    = 4'b1000;

   assign header = i_tdata_int;
   
   always @(posedge clk)
     if(reset | clear)
       dm_state <= DM_IDLE;
     else
       case (dm_state)
	 DM_IDLE :
	   if(i_tvalid_int)
	     case(dest)
	       2'b00 : dm_state <= DM_0;
	       2'b01 : dm_state <= DM_1;
	       2'b10 : dm_state <= DM_2;
	       2'b11 : dm_state <= DM_3;
	     endcase // case (i_tdata[1:0])
	 
	 DM_0, DM_1, DM_2, DM_3 :
	   if(i_tvalid_int & i_tready_int & i_tlast_int)
	     dm_state <= DM_IDLE;
	 
	 default :
	   dm_state <= DM_IDLE;
       endcase // case (dm_state)

   assign {o3_tvalid, o2_tvalid, o1_tvalid, o0_tvalid} = dm_state & {4{i_tvalid_int}};
   assign i_tready_int = |(dm_state & ({o3_tready, o2_tready, o1_tready, o0_tready} | ~ACTIVE_CHAN));
      
   assign {o0_tlast, o0_tdata} = {i_tlast_int, i_tdata_int};
   assign {o1_tlast, o1_tdata} = {i_tlast_int, i_tdata_int};
   assign {o2_tlast, o2_tdata} = {i_tlast_int, i_tdata_int};
   assign {o3_tlast, o3_tdata} = {i_tlast_int, i_tdata_int};
   
endmodule // axi_demux4
module axi_mux_select #(
  parameter WIDTH = 32,
  parameter PRE_FIFO_SIZE = 0,
  parameter POST_FIFO_SIZE = 0,
  parameter SWITCH_ON_LAST = 0, // Wait until tlast is asserted before updating
  parameter SIZE = 4)
(
  input clk, input reset, input clear,
  input [$clog2(SIZE)-1:0] select,
  input [SIZE*WIDTH-1:0] i_tdata, input [SIZE-1:0] i_tlast, input [SIZE-1:0] i_tvalid, output [SIZE-1:0] i_tready,
  output [WIDTH-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready
);

  wire [WIDTH*SIZE-1:0] i_tdata_int;
  wire [WIDTH-1:0] i_tdata_arr[0:SIZE-1];
  wire [SIZE-1:0] i_tlast_int, i_tvalid_int, i_tready_int;

  wire [WIDTH-1:0] o_tdata_int;
  wire o_tlast_int, o_tvalid_int, o_tready_int;

  genvar n;
  generate
    if (PRE_FIFO_SIZE == 0) begin
      assign i_tdata_int  = i_tdata;
      assign i_tlast_int  = i_tlast;
      assign i_tvalid_int = i_tvalid;
      assign i_tready     = i_tready_int;
    end else begin
      for (n = 0; n < SIZE; n = n + 1) begin
        axi_fifo #(.WIDTH(WIDTH+1), .SIZE(PRE_FIFO_SIZE)) axi_fifo (
          .clk(clk), .reset(reset), .clear(clear),
          .i_tdata({i_tlast[n],i_tdata[WIDTH*(n+1)-1:WIDTH*n]}), .i_tvalid(i_tvalid[n]), .i_tready(i_tready[n]),
          .o_tdata({i_tlast_int[n],i_tdata_int[WIDTH*(n+1)-1:WIDTH*n]}), .o_tvalid(i_tvalid_int[n]), .o_tready(i_tready_int[n]),
          .space(), .occupied());
      end
    end
  endgenerate

  // Make arrays for easier muxing
  genvar i;
  generate
    for (i = 0; i < SIZE; i = i + 1) begin
      assign i_tdata_arr[i] = i_tdata_int[WIDTH*(i+1)-1:WIDTH*i];
    end
  endgenerate

  // Switch select line either immediately or after the last word in a packet
  reg [$clog2(SIZE)-1:0] select_hold;
  generate
    if (SWITCH_ON_LAST) begin
      reg init;
      always @(posedge clk) begin
        if (reset | clear) begin
          init        <= 1'b0;
          select_hold <= 'd0;
        end else begin
          if (|i_tvalid) begin
            init        <= 1'b1;
          end
          // Set select any time after reset and before the first packet OR
          // at the end of a packet
          if (~init | (o_tlast_int & o_tvalid_int & o_tready_int)) begin
            select_hold <= select;
          end
        end
      end
    end else begin
      always @(*) begin
        select_hold <= select;
      end
    end
  endgenerate

  // Mux
  assign o_tdata_int  = i_tdata_arr[select_hold];
  assign o_tlast_int  = i_tlast_int[select_hold];
  assign o_tvalid_int = i_tvalid_int[select_hold];
  assign i_tready_int = (1'b1 << select_hold) & {SIZE{o_tready_int}};

  generate
    if(POST_FIFO_SIZE == 0) begin
      assign o_tdata = o_tdata_int;
      assign o_tlast = o_tlast_int;
      assign o_tvalid = o_tvalid_int;
      assign o_tready_int = o_tready;
    end else begin
      axi_fifo #(.WIDTH(WIDTH+1),.SIZE(POST_FIFO_SIZE)) axi_fifo (
        .clk(clk), .reset(reset), .clear(clear),
        .i_tdata({o_tlast_int,o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int),
        .o_tdata({o_tlast,o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready),
        .space(), .occupied());
    end
  endgenerate

endmodule
module axi_fifo32_to_fifo64
  (input clk, input reset, input clear,
   input [31:0] i_tdata, input [1:0] i_tuser, input i_tlast, input i_tvalid, output i_tready,
   output [63:0] o_tdata, output [2:0] o_tuser, output o_tlast, output o_tvalid, input o_tready
   );

   reg [31:0] 	 holding;

   reg 		 state;

   always @(posedge clk)
     if(reset | clear)
       state <= 0;
     else
       if(i_tvalid & i_tready)
       case(state)
	 0 : if(~i_tlast) state <= 1'b1;
    	 1 : state <= 1'b0;
	 default : state <= 1'b0;
       endcase // case (state)

   always @(posedge clk)
     if(i_tvalid & i_tready)
       holding <= i_tdata;
   
   assign i_tready = (state == 0 && !i_tlast)? 1'b1 : o_tready;
   assign o_tvalid = (state == 0 && !i_tlast)? 1'b0 : i_tvalid;
   
   assign o_tdata = (state == 0) ? {i_tdata, 32'h0} : { holding, i_tdata };
   assign o_tlast = i_tlast;

   wire [2:0] 	 occ_in = (i_tuser == 0) ? 3'd4 : {1'b0, i_tuser};
   wire [2:0] 	 occ_out = (state == 0) ? occ_in : (occ_in + 3'd4);
   
   assign o_tuser = ~o_tlast ? 3'd0 : occ_out;
   	 
endmodule // axi_fifo32_to_fifo64
module axi_loopback
 #(
   parameter WIDTH = 64
  )
  (
   input clk,
   input reset,
   // Input AXIS
   input [WIDTH-1:0] i_tdata,
   input i_tlast,
   input i_tvalid,
   output i_tready,
   // Output AXIS
   output [WIDTH-1:0] o_tdata,
   output o_tlast,
   output o_tvalid,
   input o_tready
   );

   wire [WIDTH-1:0]     fifoin_tdata,fifoout_tdata,dmux_tdata;
   wire                 fifoin_tlast,dmux_tlast;
   wire                 fifoin_tvalid,dmux_tvalid;
   wire                 fifoin_tready,dmux_tready;
   
   // Since most real endpoints go via Demux4 place one in here to look for bugs.
   axi_demux4 #(.ACTIVE_CHAN(4'b0001), .WIDTH(WIDTH)) demux
     (.clk(clk), .reset(reset), .clear(1'b0),
      .header(), .dest(2'b00),
      .i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
      .o0_tdata(dmux_tdata), .o0_tlast(dmux_tlast), .o0_tvalid(dmux_tvalid), .o0_tready(dmux_tready), 
      .o1_tdata(), .o1_tlast(), .o1_tvalid(), .o1_tready(1'b1), 
      .o2_tdata(), .o2_tlast(), .o2_tvalid(), .o2_tready(1'b1), 
      .o3_tdata(), .o3_tlast(), .o3_tvalid(), .o3_tready(1'b1));

   axi_fifo_short #(.WIDTH(WIDTH+1)) axi_fifo_short1
     (.clk(clk), .reset(reset), .clear(1'b0),
      .i_tdata({dmux_tlast,dmux_tdata}), .i_tvalid(dmux_tvalid), .i_tready(dmux_tready),
      .o_tdata({fifoin_tlast,fifoin_tdata}), .o_tvalid(fifoin_tvalid), .o_tready(fifoin_tready),
      .space(), .occupied());

   reg header;
   always @(posedge clk) begin
     if(reset) begin
       header <= 1'b1;
     end else if (header) begin
       if(fifoin_tvalid & fifoin_tready & ~fifoin_tlast) header <= 1'b0;
     end else begin
       if(fifoin_tvalid & fifoin_tready & fifoin_tlast) header <= 1'b1;
     end
   end

   assign fifoout_tdata = header ? 
			       {fifoin_tdata[63:32] ,fifoin_tdata[15:0],fifoin_tdata[31:16]} :
			       fifoin_tdata;
   
   axi_fifo_short #(.WIDTH(WIDTH+1)) axi_fifo_short2
     (.clk(clk), .reset(reset), .clear(1'b0),
      .i_tdata({fifoin_tlast,fifoout_tdata}), .i_tvalid(fifoin_tvalid), .i_tready(fifoin_tready),
      .o_tdata({o_tlast,o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready),
      .space(), .occupied());

endmodule // axi_loopback
module axi_mux4
  #(parameter PRIO=0,
    parameter WIDTH=64,
    parameter BUFFER=0)
   (input clk, input reset, input clear,
    input [WIDTH-1:0] i0_tdata, input i0_tlast, input i0_tvalid, output i0_tready,
    input [WIDTH-1:0] i1_tdata, input i1_tlast, input i1_tvalid, output i1_tready,
    input [WIDTH-1:0] i2_tdata, input i2_tlast, input i2_tvalid, output i2_tready,
    input [WIDTH-1:0] i3_tdata, input i3_tlast, input i3_tvalid, output i3_tready,
    output [WIDTH-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready);

   wire [WIDTH-1:0]    o_tdata_int;
   wire 	       o_tlast_int, o_tvalid_int, o_tready_int;
   
   reg [3:0] 	  mx_state;
   localparam MX_IDLE = 4'b0000;
   localparam MX_0    = 4'b0001;
   localparam MX_1    = 4'b0010;
   localparam MX_2    = 4'b0100;
   localparam MX_3    = 4'b1000;

   always @(posedge clk)
     if(reset | clear)
       mx_state <= MX_IDLE;
     else
       case (mx_state)
	 MX_IDLE :
	   if(i0_tvalid)
	     mx_state <= MX_0;
	   else if(i1_tvalid)
	     mx_state <= MX_1;
	   else if(i2_tvalid)
	     mx_state <= MX_2;
	   else if(i3_tvalid)
	     mx_state <= MX_3;

	 MX_0 :
	   if(o_tready_int & o_tvalid_int & o_tlast_int)
	     if(PRIO)
	       mx_state <= MX_IDLE;
	     else if(i1_tvalid)
	       mx_state <= MX_1;
	     else if(i2_tvalid)
	       mx_state <= MX_2;
	     else if(i3_tvalid)
	       mx_state <= MX_3;
	     else
	       mx_state <= MX_IDLE;
	 	 
	 MX_1 :
	   if(o_tready_int & o_tvalid_int & o_tlast_int)
	     if(PRIO)
	       mx_state <= MX_IDLE;
	     else if(i2_tvalid)
	       mx_state <= MX_2;
	     else if(i3_tvalid)
	       mx_state <= MX_3;
	     else
	       mx_state <= MX_IDLE;

	 MX_2 :
	   if(o_tready_int & o_tvalid_int & o_tlast_int)
	     if(PRIO)
	       mx_state <= MX_IDLE;
	     else if(i3_tvalid)
	       mx_state <= MX_3;
	     else
	       mx_state <= MX_IDLE;
	 	 
	 MX_3 :
	   if(o_tready_int & o_tvalid_int & o_tlast_int)
	     if(PRIO)
	       mx_state <= MX_IDLE;
	     else
	       mx_state <= MX_IDLE;
	 	 
	 default :
	   mx_state <= MX_IDLE;
       endcase // case (mx_state)

   assign {i3_tready, i2_tready, i1_tready, i0_tready} = mx_state & {4{o_tready_int}};

   assign o_tvalid_int = |(mx_state & ({i3_tvalid, i2_tvalid, i1_tvalid, i0_tvalid}));
         
   assign {o_tlast_int, o_tdata_int} = mx_state[3] ? {i3_tlast, i3_tdata} :
				       mx_state[2] ? {i2_tlast, i2_tdata} :
				       mx_state[1] ? {i1_tlast, i1_tdata} :
				       {i0_tlast, i0_tdata};

   generate
      if(BUFFER == 0)
	begin
	   assign o_tdata = o_tdata_int;
	   assign o_tlast = o_tlast_int;
	   assign o_tvalid = o_tvalid_int;
	   assign o_tready_int = o_tready;
	end
      else
	axi_fifo_flop2 #(.WIDTH(WIDTH+1)) axi_fifo_flop2
	  (.clk(clk), .reset(reset), .clear(clear),
	   .i_tdata({o_tlast_int,o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int),
	   .o_tdata({o_tlast,o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready),
	   .space(), .occupied());
   endgenerate
   
endmodule // axi__mux4
module axi_fifo_cascade
  #(parameter WIDTH=32, SIZE=9)
   (input clk, input reset, input clear,
    input [WIDTH-1:0] i_tdata,
    input i_tvalid,
    output i_tready,
    output [WIDTH-1:0] o_tdata,
    output o_tvalid,
    input o_tready,
    
    output [15:0] space,
    output [15:0] occupied);

   wire [WIDTH-1:0]   int1_tdata, int2_tdata;
   wire 	      int1_tvalid, int1_tready, int2_tvalid, int2_tready;
   
   axi_fifo_flop2 #(.WIDTH(WIDTH)) pre_fifo
     (.clk(clk), .reset(reset), .clear(clear),
      .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready),
      .o_tdata(int1_tdata), .o_tvalid(int1_tvalid), .o_tready(int1_tready),
      .space(), .occupied());

   axi_fifo #(.WIDTH(WIDTH), .SIZE(SIZE)) main_fifo
     (.clk(clk), .reset(reset), .clear(clear),
      .i_tdata(int1_tdata), .i_tvalid(int1_tvalid), .i_tready(int1_tready),
      .o_tdata(int2_tdata), .o_tvalid(int2_tvalid), .o_tready(int2_tready),
      .space(space), .occupied(occupied));   // May change unexpectedly, but are always conservative
  
   axi_fifo_flop2 #(.WIDTH(WIDTH)) post_fifo
     (.clk(clk), .reset(reset), .clear(clear),
      .i_tdata(int2_tdata), .i_tvalid(int2_tvalid), .i_tready(int2_tready),
      .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready),
      .space(), .occupied());

endmodule // axi_fifo_cascade
module axi_mux
  #(parameter PRIO=0,
    parameter WIDTH=64,
    parameter PRE_FIFO_SIZE=0,
    parameter POST_FIFO_SIZE=0,
    parameter SIZE=4)
   (input clk, input reset, input clear,
    input [(WIDTH*SIZE)-1:0] i_tdata, input [SIZE-1:0] i_tlast, input [SIZE-1:0] i_tvalid, output [SIZE-1:0] i_tready,
    output [WIDTH-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready);

   wire [WIDTH*SIZE-1:0] i_tdata_int;
   wire [SIZE-1:0] i_tlast_int, i_tvalid_int, i_tready_int;

   wire [WIDTH-1:0] o_tdata_int;
   wire o_tlast_int, o_tvalid_int, o_tready_int;

   reg [$clog2(SIZE)-1:0] 	       st_port;
   reg 		       st_active;

  genvar n;
  generate
    if (PRE_FIFO_SIZE == 0) begin
      assign i_tdata_int  = i_tdata;
      assign i_tlast_int  = i_tlast;
      assign i_tvalid_int = i_tvalid;
      assign i_tready     = i_tready_int;
    end else begin
      for (n = 0; n < SIZE; n = n + 1) begin
        axi_fifo #(.WIDTH(WIDTH+1), .SIZE(PRE_FIFO_SIZE)) axi_fifo (
          .clk(clk), .reset(reset), .clear(clear),
          .i_tdata({i_tlast[n],i_tdata[WIDTH*(n+1)-1:WIDTH*n]}), .i_tvalid(i_tvalid[n]), .i_tready(i_tready[n]),
          .o_tdata({i_tlast_int[n],i_tdata_int[WIDTH*(n+1)-1:WIDTH*n]}), .o_tvalid(i_tvalid_int[n]), .o_tready(i_tready_int[n]),
          .space(), .occupied());
      end
    end
  endgenerate

   always @(posedge clk)
     if(reset)
       begin
	  st_port <= 0;
	  st_active <= 1'b0;
       end
     else
       if(st_active)
	 begin
	    if(o_tlast_int & o_tvalid_int & o_tready_int)
	      begin
		 st_active <= 1'b0;
		 if((PRIO != 0) | (st_port == (SIZE-1)))
		   st_port <= 0;
		 else
		   st_port <= st_port + 1;
	      end
	 end // if (st_active)
       else
	 if(i_tvalid_int[st_port])
	   st_active <= 1'b1;
	 else
	   if(st_port == (SIZE-1))
	     st_port <= 0;
	   else
	     st_port <= st_port + 1;
   
   genvar 		 i;
   generate
      for(i=0;i<SIZE;i=i+1)
	begin : gen1
	   assign i_tready_int[i] = st_active & o_tready_int & (st_port == i);
	end
   endgenerate

   assign o_tvalid_int = st_active & i_tvalid_int[st_port];
   assign o_tlast_int = i_tlast_int[st_port];

   genvar 		 j;
   generate
      for (j=0;j<WIDTH;j=j+1)
	begin : gen2
	   assign o_tdata_int[j] = i_tdata_int[st_port*WIDTH+j];
	end
   endgenerate
   
   generate
      if(POST_FIFO_SIZE == 0)
	begin
	   assign o_tdata = o_tdata_int;
	   assign o_tlast = o_tlast_int;
	   assign o_tvalid = o_tvalid_int;
	   assign o_tready_int = o_tready;
	end
      else
	axi_fifo #(.WIDTH(WIDTH+1),.SIZE(POST_FIFO_SIZE)) axi_fifo
	  (.clk(clk), .reset(reset), .clear(clear),
	   .i_tdata({o_tlast_int,o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int),
	   .o_tdata({o_tlast,o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready),
	   .space(), .occupied());
   endgenerate
   
endmodule // axi__mux
module chdr_16sc_to_32f_tb();

   reg clk = 0;
   reg reset = 1;
   //generate clock
   always #10 clk = ~clk; 

   initial $dumpfile("chdr_16sc_to_32f_tb.vcd");
   initial $dumpvars(0,chdr_16sc_to_32f_tb);
   

   //tells when to finish
   initial
     begin
   	#50 reset = 0;
   	#50000; 
   	$finish;
     end

   //setting registers and wire
   reg [63:0] i_tdata;
   reg        i_tlast = 0;
   reg        i_tvalid = 0;
   wire       i_tready ;
   reg [7:0] set_addr;
   reg [31:0] set_data;
   reg set_stb;
   

   wire [63:0] o_tdata;
   wire        o_tlast;
   
   wire	       o_tvalid;
   reg 	       o_tready;

   chdr_16sc_to_32f #(.BASE(89))dut
    (.clk(clk), .reset(reset),
       .set_data(set_data), .set_stb(set_stb), .set_addr(set_addr),
      .i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
      .o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready), .debug());
   

//change [15:0] to whatever amount of samples you want to test. however float to iq was tested thouroughly independently. so it works
  reg [15:0]data[0:15];
  initial $readmemh("iq_to_float_input.txt", data);

//test packet loop
  task test_packet;
      input [15:0] len;
      input [31:0] sid;
      reg [3:0] index;
            
      begin

	  index <= 0;
	 
	 
	 @(posedge clk);
	 //send header 
   	 i_tdata <= {1'b0, 1'b0, 1'b1, 1'b0, 12'h0, (len + 16'd16),sid};
	 i_tvalid <= 1;
	 i_tlast <= 0;
	 
	 @(posedge clk);
	 while (i_tready != 1)
	   @(posedge clk);
	 i_tdata <= {64'b0};
	 
   	 @(posedge clk);
	 while (i_tready != 1)
	   @(posedge clk);
     //-1 for last bit accounting
	  repeat (len[15:3] + (len[2]|len[1]|len[0])-1)
	   begin
	      i_tdata <= {data[index], data[index+1], data[index+2], data[index+3]}; 
   	      index <= index+4;
	      
	      @(posedge clk);
	      while (i_tready != 1)
		@(posedge clk);
	   end
   	 i_tlast <= 1'b1;
	 i_tdata <= {data[index], data[index+1], data[index+2], data[index+3]}; 
	 
   
	 @(posedge clk);
	 while (i_tready != 1)
	   @(posedge clk);
	 i_tvalid <= 0;
      end
   endtask // test_packet

//test_destination loop

   task test_destination;
      input enable;
      input [15:0] dest_home;
      
      
      begin
         @(posedge clk);
            
         set_data <= {enable,dest_home};
         set_addr <= 89;
         set_stb <= 1;
            
         @(posedge clk);
         set_stb <= 0;
         end
      endtask
	
//main loop	
   initial
     begin
	i_tvalid <= 0;
	o_tready <= 1;
	
    i_tdata <= 0;
   
	@(negedge reset);
	@(posedge clk);
	@(posedge clk);


	test_destination(1,16'hFEED);
	test_packet(2, 32'hDEAD_BEEF);

	test_destination(1,16'hFEED);
	test_packet(4, 32'hDEAD_BEEF);

	test_destination(1,16'hFEED);
	test_packet(6, 32'hDEAD_BEEF);

	test_destination(1,16'hFEED);
	test_packet(8, 32'hDEAD_BEEF);

     end




endmodule