dakies/OSS_Verilog huggingface dataset:
module SRLC16E (Q, Q15, A0, A1, A2, A3, CE, CLK, D);

    parameter INIT = 16'h0000;

    output Q, Q15;

    input  A0, A1, A2, A3, CE, CLK, D;

    reg  [15:0] data;
    wire [3:0]  addr;
    wire	q_int;

    buf b_a3 (addr[3], A3);
    buf b_a2 (addr[2], A2);
    buf b_a1 (addr[1], A1);
    buf b_a0 (addr[0], A0);

    buf b_q_int (q_int, data[addr]);
    buf b_q (Q, q_int);
    buf b_q15_int (q15_int, data[15]);
    buf b_q15 (Q15, q15_int);

    initial
    begin
          assign  data = INIT;
          while (CLK === 1'b1 || CLK===1'bX) 
            #10; 
          deassign data;
    end

    always @(posedge CLK) begin
	if (CE == 1'b1) begin
	    {data[15:0]} <= #100 {data[14:0], D};
	end
    end


endmodule
module adc_model
  (input clk, input rst,
   output [13:0] adc_a,
   output adc_ovf_a,
   input adc_on_a,
   input adc_oe_a,
   output [13:0] adc_b,
   output adc_ovf_b,
   input adc_on_b,
   input adc_oe_b
   );
   
   math_real math ( ) ;

   reg [13:0] adc_a_int = 0;
   reg [13:0] adc_b_int = 0;
   
   assign     adc_a = adc_oe_a ? adc_a_int : 14'bz;
   assign     adc_ovf_a = adc_oe_a ? 1'b0 : 1'bz;
   assign     adc_b = adc_oe_b ? adc_b_int : 14'bz;
   assign     adc_ovf_b = adc_oe_b ? 1'b0 : 1'bz;
   
   real       phase = 0;
   real       freq = 330000/100000000;

   real       scale = 8190; // math.pow(2,13)-2;
   always @(posedge clk)
     if(rst)
       begin
	  adc_a_int <= 0;
	  adc_b_int <= 0;
       end
     else 
       begin
	  if(adc_on_a)
	    //adc_a_int <= $rtoi(math.round(math.sin(phase*math.MATH_2_PI)*scale)) ;
	    adc_a_int <= adc_a_int + 3;
	  if(adc_on_b)
	    adc_b_int <= adc_b_int - 7;
	  //adc_b_int <= $rtoi(math.round(math.cos(phase*math.MATH_2_PI)*scale)) ;
	  if(phase > 1)
	    phase <= phase + freq - 1;
	  else
	    phase <= phase + freq;
       end
   
endmodule // adc_model
module serdes_model
  (input ser_tx_clk,
   input ser_tkmsb,
   input ser_tklsb,
   input [15:0] ser_t,
   
   output ser_rx_clk,
   output ser_rkmsb,
   output ser_rklsb,
   output [15:0] ser_r,
   
   input even,
   input error);
   
   wire [15:0] ser_r_odd;
   wire  ser_rklsb_odd, ser_rkmsb_odd;   
   
   reg [7:0] hold_dat;
   reg 	     hold_k;
   
   always @(posedge ser_tx_clk) hold_k <= ser_tklsb;
   always @(posedge ser_tx_clk) hold_dat <= ser_t[15:8];
   assign    ser_rklsb_odd = hold_k;
   assign    ser_rkmsb_odd = ser_tklsb;
   assign    ser_r_odd = {ser_t[7:0], hold_dat};
   
   // Set outputs
   assign    ser_rx_clk = ser_tx_clk;
   assign    ser_rkmsb = even ? ser_tkmsb : ser_rkmsb_odd;
   assign    ser_rklsb = even ? ser_tklsb : ser_rklsb_odd;
   assign    ser_r = error ^ (even ? ser_t : ser_r_odd);
   
endmodule // serdes_model
module IBUFG (O, I);

    parameter CAPACITANCE = "DONT_CARE";
    parameter IBUF_DELAY_VALUE = "0";
    parameter IOSTANDARD = "DEFAULT";

    output O;
    input  I;

    buf B1 (O, I);
    
    initial begin
	
        case (CAPACITANCE)

            "LOW", "NORMAL", "DONT_CARE" : ;
            default : begin
                          $display("Attribute Syntax Error : The attribute CAPACITANCE on IBUFG instance %m is set to %s.  Legal values for this attribute are DONT_CARE, LOW or NORMAL.", CAPACITANCE);
                          $finish;
                      end

        endcase


	case (IBUF_DELAY_VALUE)

            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16" : ;
            default : begin
                          $display("Attribute Syntax Error : The attribute IBUF_DELAY_VALUE on IBUFG instance %m is set to %s.  Legal values for this attribute are 0, 1, 2, ... or 16.", IBUF_DELAY_VALUE);
                          $finish;
                      end

        endcase

    end // initial begin
    
endmodule
module phy_sim(
  input        Gtx_clk, // Used only in GMII mode
  output       Rx_clk,
  output       Tx_clk, // Used only in MII mode
  input        Tx_er,
  input        Tx_en,
  input  [7:0] Txd,
  output       Rx_er,
  output       Rx_dv,
  output [7:0] Rxd,
  output       Crs,
  output       Col,
  input  [2:0] Speed,
  input        Done
);

//////////////////////////////////////////////////////////////////////
// this file used to simulate Phy.
// generate clk and loop the Tx data to Rx data
// full duplex mode can be verified on loop mode.
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// internal signals
//////////////////////////////////////////////////////////////////////
reg Clk_25m;  // Used for 100 Mbps mode
reg Clk_2_5m; // Used for 10 Mbps mode

//wire Rx_clk;
//wire Tx_clk; // Used only in MII mode

  initial 
    begin
      #10;
      while ( !Done )
        begin
          #20 Clk_25m = 0;
          #20 Clk_25m = 1;
        end
    end

  initial 
    begin
      #10;
      while ( !Done )
        begin
          #200 Clk_2_5m = 0;
          #200 Clk_2_5m = 1;
        end
    end

  assign Rx_clk = Speed[2] ? Gtx_clk : Speed[1] ? Clk_25m : Speed[0] ? Clk_2_5m : 0;        
  assign Tx_clk = Speed[2] ? Gtx_clk : Speed[1] ? Clk_25m : Speed[0] ? Clk_2_5m : 0;

  assign Rx_dv = Tx_en;
  assign Rxd   = Txd;
  assign Rx_er = Tx_er;
  assign Crs   = Tx_en;
  assign Col   = 0;

endmodule
module IOBUF (O, IO, I, T);

    parameter CAPACITANCE = "DONT_CARE";
    parameter integer DRIVE = 12;
    parameter IBUF_DELAY_VALUE = "0";
    parameter IFD_DELAY_VALUE = "AUTO";
    parameter IOSTANDARD = "DEFAULT";
    parameter SLEW = "SLOW";

    output O;
    inout  IO;
    input  I, T;

    wire ts;

    //tri0 GTS = glbl.GTS;

    or O1 (ts, GTS, T);
    bufif0 T1 (IO, I, ts);

    buf B1 (O, IO);

    initial begin
	
        case (CAPACITANCE)

            "LOW", "NORMAL", "DONT_CARE" : ;
            default : begin
                          $display("Attribute Syntax Error : The attribute CAPACITANCE on IOBUF instance %m is set to %s.  Legal values for this attribute are DONT_CARE, LOW or NORMAL.", CAPACITANCE);
                          $finish;
                      end

        endcase

	case (IBUF_DELAY_VALUE)

            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16" : ;
            default : begin
                          $display("Attribute Syntax Error : The attribute IBUF_DELAY_VALUE on IOBUF instance %m is set to %s.  Legal values for this attribute are 0, 1, 2, ... or 16.", IBUF_DELAY_VALUE);
                          $finish;
                      end

        endcase


	case (IFD_DELAY_VALUE)

            "AUTO", "0", "1", "2", "3", "4", "5", "6", "7", "8" : ;
            default : begin
                          $display("Attribute Syntax Error : The attribute IFD_DELAY_VALUE on IOBUF instance %m is set to %s.  Legal values for this attribute are AUTO, 0, 1, 2, ... or 8.", IFD_DELAY_VALUE);
                          $finish;
                      end

	endcase
	
    end // initial begin
    
endmodule
module xlnx_glbl
(
  GSR,
  GTS
);

  //--------------------------------------------------------------------------
  // Parameters
  //--------------------------------------------------------------------------

  //--------------------------------------------------------------------------
  // IO declarations
  //--------------------------------------------------------------------------

  output GSR;
  output GTS;

  //--------------------------------------------------------------------------
  // Local declarations
  //--------------------------------------------------------------------------

  //--------------------------------------------------------------------------
  // Internal declarations
  //--------------------------------------------------------------------------

  assign GSR = 0;
  assign GTS = 0;
  
endmodule
module IBUFGDS (O, I, IB);

    parameter CAPACITANCE = "DONT_CARE";   
    parameter DIFF_TERM = "FALSE";
    parameter IBUF_DELAY_VALUE = "0";
    parameter IOSTANDARD = "DEFAULT";
   
    output O;
    input  I, IB;

    reg o_out;

    buf b_0 (O, o_out);

    initial begin
	
        case (CAPACITANCE)

            "LOW", "NORMAL", "DONT_CARE" : ;
            default : begin
                          $display("Attribute Syntax Error : The attribute CAPACITANCE on IBUFGDS instance %m is set to %s.  Legal values for this attribute are DONT_CARE, LOW or NORMAL.", CAPACITANCE);
                          $finish;
                      end

        endcase

	
	case (DIFF_TERM)

            "TRUE", "FALSE" : ;
            default : begin
                          $display("Attribute Syntax Error : The attribute DIFF_TERM on IBUFGDS instance %m is set to %s.  Legal values for this attribute are TRUE or FALSE.", DIFF_TERM);
                          $finish;
                      end

	endcase

	
	case (IBUF_DELAY_VALUE)

            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16" : ;
            default : begin
                          $display("Attribute Syntax Error : The attribute IBUF_DELAY_VALUE on IBUFGDS instance %m is set to %s.  Legal values for this attribute are 0, 1, 2, ... or 16.", IBUF_DELAY_VALUE);
                          $finish;
                      end

        endcase
	
    end
    
    always @(I or IB) begin
	if (I == 1'b1 && IB == 1'b0)
	    o_out <= I;
	else if (I == 1'b0 && IB == 1'b1)
	    o_out <= I;
        else if (I == 1'bx && IB == 1'bx)
            o_out <= 1'bx;
    end

endmodule
module uart_rx (input baudclk, input rxd);
   reg [8:0] sr = 9'b0;
   reg [3:0]  baud_ctr = 4'b0;

   /*
   wire       byteclk = baud_ctr[3];
   reg 	      rxd_d1 = 0;
   always @(posedge baudclk)
     rxd_d1 <= rxd;
   
   always @(posedge baudclk)
     if(rxd_d1 != rxd)
       baud_ctr <= 0;
     else
       baud_ctr <= baud_ctr + 1;
*/

   wire       byteclk = baudclk;
   
   always @(posedge byteclk)
     sr <= { rxd, sr[8:1] };

   reg [3:0]  state = 0;
   always @(posedge byteclk)
     case(state)
       0 : 
	 if(~sr[8] & sr[7])  // found start bit
	   state  <= 1;
       1, 2, 3, 4, 5, 6, 7, 8 :
	 state <= state + 1;
       9 : 
	 begin
	    state <= 0;
	    $write("%c",sr[7:0]);
	    if(~sr[8])
	      $display("Error, no stop bit\n");
	 end
       default :
	 state <= 0;
     endcase // case(state)

endmodule // uart_rx
module miim_model(input mdc_i, 
		  inout mdio, 
		  input phy_resetn_i, 
		  input phy_clk_i, 
		  output phy_intn_o,
		  output [2:0] speed_o);

   assign 		       phy_intn_o = 1;    // No interrupts
   assign 		       speed_o = 3'b100;  // 1G mode
   
endmodule // miim_model
module gpmc_model_sync
  (output reg EM_CLK, inout [15:0] EM_D, output reg [10:1] EM_A, output reg [1:0] EM_NBE,
   output reg EM_WAIT0, output reg EM_NCS4, output reg EM_NCS6, 
   output reg EM_NWE, output reg EM_NOE );

   reg [15:0] EM_D_int;
   assign EM_D = EM_D_int;

   initial
     begin
	EM_CLK <= 0;
	EM_A <= 10'bz;
	EM_NBE <= 2'b11;
	EM_NWE <= 1;
	EM_NOE <= 1;
	EM_NCS4 <= 1;
	EM_NCS6 <= 1;
	EM_D_int <= 16'bz;
 	EM_WAIT0 <= 0;  // FIXME this is actually an input
     end
   
   task GPMC_Write;
      input ctrl;
      input [10:0] addr;
      input [15:0] data;
      begin
	 EM_CLK <= 1;
	 #10;
	 EM_CLK <= 0;
	 EM_NWE <= 0;
	 if(ctrl)
	   EM_NCS6 <= 0;
	 else
	   EM_NCS4 <= 0;
	 EM_A <= addr[10:1];
	 EM_D_int <= data;
	 #10;
	 EM_CLK <= 1;
	 #10;
	 EM_CLK <= 0;
	 EM_NWE <= 1;
	 EM_NCS4 <= 1;
	 EM_NCS6 <= 1;
	 EM_A <= 10'bz;
	 EM_D_int <= 16'bz;
	 #100;
      end
   endtask // GPMC_Write

   task GPMC_Read;
      input ctrl;
      input [10:0] addr;
      begin
	 #1.3;
	 EM_A <= addr[10:1];
	 #3;
	 if(ctrl)
	   EM_NCS6 <= 0;
	 else
	   EM_NCS4 <= 0;
	 #14;
	 EM_NOE <= 0;
	 #77.5;
	 EM_NCS4 <= 1;
	 EM_NCS6 <= 1;
	 //#1.5;
	 $display("Data Read from GPMC: %X",EM_D);
	 EM_NOE <= 1;
	 #254;
	 EM_A <= 10'bz;
      end
   endtask // GPMC_Read
   
   initial
     begin
	#1000;
	GPMC_Write(1,36,16'hF00D);
	#1000;
	GPMC_Read(1,36);
	#1000;
	GPMC_Write(0,36,16'h1234);
	GPMC_Write(0,38,16'h5678);
	GPMC_Write(0,40,16'h9abc);
	GPMC_Write(0,11'h2F4,16'hF00D);
	GPMC_Write(0,11'h7FE,16'hDEAD);
	GPMC_Write(0,11'h7FE,16'hDEAD);
	GPMC_Write(0,11'h7FE,16'hDEAD);
	GPMC_Write(0,11'h7FE,16'hDEAD);
	GPMC_Write(0,11'h7FE,16'hDEAD);
	GPMC_Write(0,11'h7FE,16'hDEAD);
	#100000;
	$finish;
     end
   
endmodule // gpmc_model
module cpld_model
  (input aux_clk, input start, input mode, input done,
   output dout, output reg sclk, output detached);

   reg [7:0] rom[0:65535];

   reg [15:0] addr;
   reg [7:0]  data;
   assign     dout = data[7];

   reg [2:0]  state, bitcnt;
   
   localparam IDLE = 3'd0;
   localparam READ = 3'd1;
   localparam BIT1 = 3'd2;
   localparam BIT2 = 3'd3;
   localparam DONE = 3'd4;
   localparam DETACHED = 3'd5;
   localparam ERROR = 3'd7;
   
   integer i; 
   reg [1023:0] ROMFile;
   
   initial begin
      for (i=0;i<65536;i=i+1) begin
	 rom[i] <= 32'h0;
      end       
      if ( !$value$plusargs( "rom=%s", ROMFile ) )
        begin
           $display( "Using default ROM file, 'flash.rom'" );
           ROMFile = "flash.rom";
        end
      else
	$display( "Using %s as ROM file.", ROMFile);
      
      #1 $readmemh( ROMFile,rom );     
   end

   initial addr = 16'd0;
   initial data = 8'd0;
   initial state = IDLE;
   initial bitcnt = 3'd0;
   initial sclk = 1'b0;
   
   always @(posedge aux_clk)
     case(state)
       IDLE :
	 if(start)
	   if(~mode)
	     state <= READ;
	   else
	     state <= ERROR;
       READ :
	 if(done)
	   state <= DONE;
       	 else
	   begin
	      data <= rom[addr];
	      addr <= addr + 1;
	      bitcnt <= 3'd0;
	      if(addr==16'hFFFF)
		state <= ERROR;
	      else
		state <= BIT1;
	   end // else: !if(start)
       BIT1 :
	 begin
	    sclk <= 1'b1;
	    state <= BIT2;
	 end
       BIT2 :
	 begin
	    sclk <= 1'b0;
	    data <= {data[6:0],1'b0};
	    bitcnt <= bitcnt + 1;
	    if(bitcnt==7)
	      state <= READ;
	    else
	      state <=BIT1;
	 end
       DONE :
	 begin
	    if(start)
	      state <= ERROR;
	    else
	      state <= DETACHED;
	 end
       DETACHED :
	 if(start)
	   state <= ERROR;
     endcase // case(state)
   
   assign detached = (state == DETACHED) || (state == IDLE);
   
endmodule // cpld_model
module gpmc_model_async
  (output EM_CLK, inout [15:0] EM_D, output reg [10:1] EM_A, output reg [1:0] EM_NBE,
   output reg EM_WAIT0, output reg EM_NCS4, output reg EM_NCS6, 
   output reg EM_NWE, output reg EM_NOE );

   assign EM_CLK = 0;
   reg [15:0] EM_D_int;
   assign EM_D = EM_D_int;
   
   initial
     begin
	EM_A <= 10'bz;
	EM_NBE <= 2'b11;
	EM_NWE <= 1;
	EM_NOE <= 1;
	EM_NCS4 <= 1;
	EM_NCS6 <= 1;
	EM_D_int <= 16'bz;
 	EM_WAIT0 <= 0;  // FIXME this is actually an input
     end
   
   task GPMC_Write;
      input ctrl;
      input [10:0] addr;
      input [15:0] data;
      begin
	 #23000;
	 EM_A <= addr[10:1];
	 EM_D_int <= data;
	 #20100;
	 if(ctrl)
	   EM_NCS6 <= 0;
	 else
	   EM_NCS4 <= 0;
	 #14000;
	 EM_NWE <= 0;
	 #77500;
	 EM_NCS4 <= 1;
	 EM_NCS6 <= 1;
	 //#1.5;
	 EM_NWE <= 1;
	 #60000;
	 EM_A <= 10'bz;
	 EM_D_int <= 16'bz;
      end
   endtask // GPMC_Write

   task GPMC_Read;
      input ctrl;
      input [10:0] addr;
      begin
	 #13000;
	 EM_A <= addr[10:1];
	 #3000;
	 if(ctrl)
	   EM_NCS6 <= 0;
	 else
	   EM_NCS4 <= 0;
	 #14000;
	 EM_NOE <= 0;
	 #77500;
	 EM_NCS4 <= 1;
	 EM_NCS6 <= 1;
	 //#1.5;
	 $display("Data Read from GPMC: %X",EM_D);
	 EM_NOE <= 1;
	 #254000;
	 EM_A <= 10'bz;
      end
   endtask // GPMC_Read
   
   initial
     begin
	#1000000;
	GPMC_Write(1,36,16'hF00D);
	#1000000;
	GPMC_Read(1,36);
	#1000000;
	GPMC_Write(0,0,16'h1234);
	GPMC_Write(0,0,16'h5678);
	GPMC_Write(0,0,16'h9abc);
	GPMC_Write(0,0,16'hF00D);
	GPMC_Write(0,0,16'hDEAD);
	GPMC_Write(0,0,16'hDEAD);
	GPMC_Write(0,0,16'hDEAD);
	GPMC_Write(0,0,16'hDEAD);
	GPMC_Write(0,0,16'hDEAD);
	GPMC_Write(0,0,16'hDEAD);
	#1000000;
	GPMC_Write(0,0,16'h1234);
	GPMC_Write(0,0,16'h5678);
	GPMC_Write(0,0,16'h9abc);
	GPMC_Write(0,0,16'hF00D);
	GPMC_Write(0,0,16'hDEAD);
	GPMC_Write(0,0,16'hDEAD);
	GPMC_Write(0,0,16'hDEAD);
	GPMC_Write(0,0,16'hDEAD);
	GPMC_Write(0,0,16'hDEAD);
	GPMC_Write(0,0,16'h9876);
	#1000000;
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	#1000000;
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	GPMC_Read(0,0);
	#1000000;
	GPMC_Read(0,0);
	#100000000;
	$finish;
     end
   
endmodule // gpmc_model_async
module cross_clock_reader
    #(
        parameter WIDTH = 1,
        parameter DEFAULT = 0
    )
    (
        input clk, input rst,
        input [WIDTH-1:0] in,
        output reg [WIDTH-1:0] out
    );

    reg [WIDTH-1:0] shadow0, shadow1;
    reg [2:0] count;

    always @(posedge clk) begin
        if (rst) begin
            out <= DEFAULT;
            shadow0 <= DEFAULT;
            shadow1 <= DEFAULT;
            count <= 0;
        end
        else if (shadow0 == shadow1) count <= count + 1;
        else count <= 0;
        shadow0 <= in;
        shadow1 <= shadow0;
        if (count == 3'b111) out <= shadow1;
    end

endmodule //cross_clock_reader
module fifo72_to_fifo36
  #(parameter LE=0)
   (input clk, input reset, input clear,
    input [71:0] f72_datain,
    input f72_src_rdy_i,
    output f72_dst_rdy_o,
    
    output [35:0] f36_dataout,
    output f36_src_rdy_o,
    input f36_dst_rdy_i );
      
   wire [35:0] f36_data_int;
   wire        f36_src_rdy_int, f36_dst_rdy_int;
   wire [71:0] f72_data_int;
   wire        f72_src_rdy_int, f72_dst_rdy_int;
   
   // Shortfifo on input to guarantee no deadlock
   fifo_short #(.WIDTH(72)) head_fifo
     (.clk(clk),.reset(reset),.clear(clear),
      .datain(f72_datain), .src_rdy_i(f72_src_rdy_i), .dst_rdy_o(f72_dst_rdy_o),
      .dataout(f72_data_int), .src_rdy_o(f72_src_rdy_int), .dst_rdy_i(f72_dst_rdy_int),
      .space(),.occupied() );

   // Main fifo72_to_fifo36, needs shortfifos to guarantee no deadlock
   wire [2:0]  f72_occ_int  = f72_data_int[68:66];
   wire        f72_sof_int  = f72_data_int[64];
   wire        f72_eof_int  = f72_data_int[65];
   
   reg 	  phase;
   wire   half_line 	   = f72_eof_int & ( (f72_occ_int==1)|(f72_occ_int==2)|(f72_occ_int==3)|(f72_occ_int==4) );
      
   assign f36_data_int[31:0]   = (LE ^ phase) ? f72_data_int[31:0] : f72_data_int[63:32];
   assign f36_data_int[32]     = phase ? 0 : f72_sof_int;
   assign f36_data_int[33]     = phase ? f72_eof_int : half_line;
   assign f36_data_int[35:34]  = f36_data_int[33] ? f72_occ_int[1:0] : 2'b00;
      
   assign f36_src_rdy_int    = f72_src_rdy_int;
   assign f72_dst_rdy_int    = (phase | half_line) & f36_dst_rdy_int;
   
   wire   f36_xfer 	   = f36_src_rdy_int & f36_dst_rdy_int;
   wire   f72_xfer 	   = f72_src_rdy_int & f72_dst_rdy_int;
   
   always @(posedge clk)
     if(reset)
       phase 		  <= 0;
     else if(f72_xfer)
       phase 		  <= 0;
     else if(f36_xfer)
       phase 		  <= 1;
   
   // Shortfifo on output to guarantee no deadlock
   fifo_short #(.WIDTH(36)) tail_fifo
     (.clk(clk),.reset(reset),.clear(clear),
      .datain(f36_data_int), .src_rdy_i(f36_src_rdy_int), .dst_rdy_o(f36_dst_rdy_int),
      .dataout(f36_dataout), .src_rdy_o(f36_src_rdy_o), .dst_rdy_i(f36_dst_rdy_i),
      .space(),.occupied() );

endmodule // fifo72_to_fifo36
module fifo19_pad
  #(parameter LENGTH=16,
    parameter PAD_VALUE=0)
   (input clk, input reset, input clear,
    input [18:0] data_i,
    input src_rdy_i,
    output dst_rdy_o,
    output [18:0] data_o,
    output src_rdy_o,
    input dst_rdy_i);

   reg [15:0] count;
   reg [1:0]  pad_state;
   localparam PAD_IDLE = 0;
   localparam PAD_TOOSHORT = 1;
   localparam PAD_LONGENOUGH = 2;
   localparam PAD_PADDING = 3;

   always @(posedge clk)
     if(reset | clear)
       pad_state <= PAD_IDLE;
     else
       case(pad_state)
	 PAD_IDLE :
	   begin
	      count <= 1;
	      pad_state <= PAD_TOOSHORT;
	   end
	 PAD_TOOSHORT :
	   if(src_rdy_i & dst_rdy_i)
	     begin
		count <= count + 1;
		if(data_i[17])
		  pad_state <= PAD_PADDING;
		else if(count == (LENGTH-1))
		  pad_state <= PAD_LONGENOUGH;
	     end
	 PAD_PADDING :
	   if(dst_rdy_i)
	     begin
		count <= count + 1;
		if(count == LENGTH)
		  pad_state <= PAD_IDLE;
	     end
	 PAD_LONGENOUGH :
	   if(src_rdy_i & dst_rdy_i & data_i[17])
	     pad_state <= PAD_IDLE;
       endcase // case (pad_state)
   
   wire passthru = (pad_state == PAD_TOOSHORT) | (pad_state == PAD_LONGENOUGH);
   
   assign dst_rdy_o = passthru ? dst_rdy_i : 1'b0;
   assign src_rdy_o = passthru ? src_rdy_i : (pad_state == PAD_PADDING);
   
   assign data_o[15:0] = (pad_state == PAD_PADDING) ? PAD_VALUE : data_i[15:0];
   assign data_o[16] = (count == 1);
   assign data_o[17] = (pad_state == PAD_LONGENOUGH) ? data_i[17] : (count == LENGTH);
   assign data_o[18] = (pad_state == PAD_LONGENOUGH) ? data_i[18] : 1'b0;
   
         
endmodule // fifo19_pad
module fifo_2clock_cascade
  #(parameter WIDTH=32, SIZE=9)
   (input wclk, input [WIDTH-1:0] datain, input src_rdy_i, output dst_rdy_o, 
    output [15:0] space, output [15:0] short_space,
    input rclk, output [WIDTH-1:0] dataout, output src_rdy_o, input dst_rdy_i, 
    output [15:0] occupied, output [15:0] short_occupied,
    input arst);
   
   wire [WIDTH-1:0] data_int1, data_int2;
   wire 	    src_rdy_int1, src_rdy_int2, dst_rdy_int1, dst_rdy_int2;
   wire [SIZE-1:0]  level_wclk, level_rclk;
   wire [4:0] 	    s1_space, s1_occupied, s2_space, s2_occupied;
   wire [15:0] 	    l_space, l_occupied;
   
   fifo_short #(.WIDTH(WIDTH)) shortfifo
     (.clk(wclk), .reset(arst), .clear(0),
      .datain(datain), .src_rdy_i(src_rdy_i), .dst_rdy_o(dst_rdy_o),
      .dataout(data_int1), .src_rdy_o(src_rdy_int1), .dst_rdy_i(dst_rdy_int1),
      .space(s1_space), .occupied(s1_occupied) );
   
   fifo_2clock #(.WIDTH(WIDTH),.SIZE(SIZE)) fifo_2clock
     (.wclk(wclk), .datain(data_int1), .src_rdy_i(src_rdy_int1), .dst_rdy_o(dst_rdy_int1), .space(l_space),
      .rclk(rclk), .dataout(data_int2), .src_rdy_o(src_rdy_int2), .dst_rdy_i(dst_rdy_int2), .occupied(l_occupied),
      .arst(arst) );
   
   fifo_short #(.WIDTH(WIDTH)) shortfifo2
     (.clk(rclk), .reset(arst), .clear(0),
      .datain(data_int2), .src_rdy_i(src_rdy_int2), .dst_rdy_o(dst_rdy_int2),
      .dataout(dataout), .src_rdy_o(src_rdy_o), .dst_rdy_i(dst_rdy_i),
      .space(s2_space), .occupied(s2_occupied));

   // Be conservative -- Only advertise space from input side of fifo, occupied from output side
   assign 	    space 	    = {11'b0,s1_space} + l_space;
   assign 	    occupied 	    = {11'b0,s2_occupied} + l_occupied;

   // For the fifo_extram, we only want to know the immediately adjacent space
   assign 	    short_space     = {11'b0,s1_space};
   assign 	    short_occupied  = {11'b0,s2_occupied};
   
endmodule // fifo_2clock_cascade
module fifo36_mux
  #(parameter prio = 0)
   (input clk, input reset, input clear,
    input [35:0] data0_i, input src0_rdy_i, output dst0_rdy_o,
    input [35:0] data1_i, input src1_rdy_i, output dst1_rdy_o,
    output [35:0] data_o, output src_rdy_o, input dst_rdy_i);

   wire [35:0] 	  data0_int, data1_int;
   wire 	  src0_rdy_int, dst0_rdy_int, src1_rdy_int, dst1_rdy_int;
   
   fifo_short #(.WIDTH(36)) mux_fifo_in0
     (.clk(clk), .reset(reset), .clear(clear),
      .datain(data0_i), .src_rdy_i(src0_rdy_i), .dst_rdy_o(dst0_rdy_o),
      .dataout(data0_int), .src_rdy_o(src0_rdy_int), .dst_rdy_i(dst0_rdy_int));

   fifo_short #(.WIDTH(36)) mux_fifo_in1
     (.clk(clk), .reset(reset), .clear(clear),
      .datain(data1_i), .src_rdy_i(src1_rdy_i), .dst_rdy_o(dst1_rdy_o),
      .dataout(data1_int), .src_rdy_o(src1_rdy_int), .dst_rdy_i(dst1_rdy_int));

   localparam MUX_IDLE0 = 0;
   localparam MUX_DATA0 = 1;
   localparam MUX_IDLE1 = 2;
   localparam MUX_DATA1 = 3;
   
   reg [1:0] 	  state;

   wire 	  eof0 = data0_int[33];
   wire 	  eof1 = data1_int[33];
   
   wire [35:0] 	  data_int;
   wire 	  src_rdy_int, dst_rdy_int;
   
   always @(posedge clk)
     if(reset | clear)
       state <= MUX_IDLE0;
     else
       case(state)
	 MUX_IDLE0 :
	   if(src0_rdy_int)
	     state <= MUX_DATA0;
	   else if(src1_rdy_int)
	     state <= MUX_DATA1;

	 MUX_DATA0 :
	   if(src0_rdy_int & dst_rdy_int & eof0)
	     state <= prio ? MUX_IDLE0 : MUX_IDLE1;

	 MUX_IDLE1 :
	   if(src1_rdy_int)
	     state <= MUX_DATA1;
	   else if(src0_rdy_int)
	     state <= MUX_DATA0;
	   
	 MUX_DATA1 :
	   if(src1_rdy_int & dst_rdy_int & eof1)
	     state <= MUX_IDLE0;
	 
	 default :
	   state <= MUX_IDLE0;
       endcase // case (state)

   assign dst0_rdy_int = (state==MUX_DATA0) ? dst_rdy_int : 0;
   assign dst1_rdy_int = (state==MUX_DATA1) ? dst_rdy_int : 0;
   assign src_rdy_int = (state==MUX_DATA0) ? src0_rdy_int : (state==MUX_DATA1) ? src1_rdy_int : 0;
   assign data_int = (state==MUX_DATA0) ? data0_int : data1_int;
   
   fifo_short #(.WIDTH(36)) mux_fifo
     (.clk(clk), .reset(reset), .clear(clear),
      .datain(data_int), .src_rdy_i(src_rdy_int), .dst_rdy_o(dst_rdy_int),
      .dataout(data_o), .src_rdy_o(src_rdy_o), .dst_rdy_i(dst_rdy_i));
endmodule // fifo36_demux
module fifo36_to_fifo19
  #(parameter LE=0)
   (input clk, input reset, input clear,
    input [35:0] f36_datain,
    input f36_src_rdy_i,
    output f36_dst_rdy_o,
    
    output [18:0] f19_dataout,
    output f19_src_rdy_o,
    input f19_dst_rdy_i );
      
   wire [18:0] f19_data_int;
   wire        f19_src_rdy_int, f19_dst_rdy_int;
   wire [35:0] f36_data_int;
   wire        f36_src_rdy_int, f36_dst_rdy_int;
   
   // Shortfifo on input to guarantee no deadlock
   fifo_short #(.WIDTH(36)) head_fifo
     (.clk(clk),.reset(reset),.clear(clear),
      .datain(f36_datain), .src_rdy_i(f36_src_rdy_i), .dst_rdy_o(f36_dst_rdy_o),
      .dataout(f36_data_int), .src_rdy_o(f36_src_rdy_int), .dst_rdy_i(f36_dst_rdy_int),
      .space(),.occupied() );

   // Main fifo36_to_fifo19, needs shortfifos to guarantee no deadlock
   wire [1:0]  f36_occ_int  = f36_data_int[35:34];
   wire        f36_sof_int  = f36_data_int[32];
   wire        f36_eof_int  = f36_data_int[33];
   
   reg 	  phase;
   wire   half_line 	   = f36_eof_int & ((f36_occ_int==1)|(f36_occ_int==2));
   
   assign f19_data_int[15:0] = (LE ^ phase) ? f36_data_int[15:0] : f36_data_int[31:16];
   assign f19_data_int[16]   = phase ? 0 : f36_sof_int;
   assign f19_data_int[17]   = phase ? f36_eof_int : half_line;
   assign f19_data_int[18]   = f19_data_int[17] & ((f36_occ_int==1)|(f36_occ_int==3));
   
   assign f19_src_rdy_int    = f36_src_rdy_int;
   assign f36_dst_rdy_int    = (phase | half_line) & f19_dst_rdy_int;
   
   wire   f19_xfer 	   = f19_src_rdy_int & f19_dst_rdy_int;
   wire   f36_xfer 	   = f36_src_rdy_int & f36_dst_rdy_int;
   
   always @(posedge clk)
     if(reset)
       phase 		  <= 0;
     else if(f36_xfer)
       phase 		  <= 0;
     else if(f19_xfer)
       phase 		  <= 1;
   
   // Shortfifo on output to guarantee no deadlock
   fifo_short #(.WIDTH(19)) tail_fifo
     (.clk(clk),.reset(reset),.clear(clear),
      .datain(f19_data_int), .src_rdy_i(f19_src_rdy_int), .dst_rdy_o(f19_dst_rdy_int),
      .dataout(f19_dataout), .src_rdy_o(f19_src_rdy_o), .dst_rdy_i(f19_dst_rdy_i),
      .space(),.occupied() );

endmodule // fifo36_to_fifo19
module buffer_pool_tb();
   
   wire wb_clk_i;
   wire wb_rst_i;
   wire wb_we_i;
   wire wb_stb_i;
   wire [15:0] wb_adr_i;
   wire [31:0] wb_dat_i;   
   wire [31:0] wb_dat_o;
   wire wb_ack_o;
   wire wb_err_o;
   wire wb_rty_o;

   wire stream_clk, stream_rst;

   wire set_stb;
   wire [7:0] set_addr;
   wire [31:0] set_data;

   wire [31:0] wr0_data, wr1_data, wr2_data, wr3_data;
   wire [31:0] rd0_data, rd1_data, rd2_data, rd3_data;
   wire [3:0]  wr0_flags, wr1_flags, wr2_flags, wr3_flags;
   wire [3:0]  rd0_flags, rd1_flags, rd2_flags, rd3_flags;
   wire        wr0_ready, wr1_ready, wr2_ready, wr3_ready;
   wire        rd0_ready, rd1_ready, rd2_ready, rd3_ready;
   wire        wr0_write, wr1_write, wr2_write, wr3_write;
   wire        rd0_read, rd1_read, rd2_read, rd3_read;

   buffer_pool dut
     (.wb_clk_i(wb_clk_i),
      .wb_rst_i(wb_rst_i),
      .wb_we_i(wb_we_i),
      .wb_stb_i(wb_stb_i),
      .wb_adr_i(wb_adr_i),
      .wb_dat_i(wb_dat_i),   
      .wb_dat_o(wb_dat_o),
      .wb_ack_o(wb_ack_o),
      .wb_err_o(wb_err_o),
      .wb_rty_o(wb_rty_o),
      
      .stream_clk(stream_clk),
      .stream_rst(stream_rst),
      
      .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
      
      .wr0_data_i(wr0_data), .wr0_write_i(wr0_write), .wr0_flags_i(wr0_flags), .wr0_ready_o(wr0_ready),
      .wr1_data_i(wr1_data), .wr1_write_i(wr1_write), .wr1_flags_i(wr1_flags), .wr1_ready_o(wr1_ready),
      .wr2_data_i(wr2_data), .wr2_write_i(wr2_write), .wr2_flags_i(wr2_flags), .wr2_ready_o(wr2_ready),
      .wr3_data_i(wr3_data), .wr3_write_i(wr3_write), .wr3_flags_i(wr3_flags), .wr3_ready_o(wr3_ready),
      
      .rd0_data_o(rd0_data), .rd0_read_i(rd0_read), .rd0_flags_o(rd0_flags), .rd0_ready_o(rd0_ready),
      .rd1_data_o(rd1_data), .rd1_read_i(rd1_read), .rd1_flags_o(rd1_flags), .rd1_ready_o(rd1_ready),
      .rd2_data_o(rd2_data), .rd2_read_i(rd2_read), .rd2_flags_o(rd2_flags), .rd2_ready_o(rd2_ready),
      .rd3_data_o(rd3_data), .rd3_read_i(rd3_read), .rd3_flags_o(rd3_flags), .rd3_ready_o(rd3_ready)
      );
   
endmodule // buffer_pool_tb
module fifo_cascade
  #(parameter WIDTH=32, SIZE=9)
    (input clk, input reset, input clear,
     input [WIDTH-1:0] datain,
     input src_rdy_i,
     output dst_rdy_o,
     output [WIDTH-1:0] dataout,
     output src_rdy_o,
     input dst_rdy_i,
     output [15:0] space,
     output [15:0] occupied);

   wire [WIDTH-1:0] data_int, data_int2;
   wire src_rdy_1, dst_rdy_1, src_rdy_2, dst_rdy_2;
   
   wire [4:0] 	    s1_space, s1_occupied, s2_space, s2_occupied;
   wire [15:0] 	    l_space, l_occupied;
   
   fifo_short #(.WIDTH(WIDTH)) head_fifo
     (.clk(clk),.reset(reset),.clear(clear),
      .datain(datain), .src_rdy_i(src_rdy_i), .dst_rdy_o(dst_rdy_o),
      .dataout(data_int), .src_rdy_o(src_rdy_1), .dst_rdy_i(dst_rdy_1),
      .space(s1_space),.occupied(s1_occupied) );
      
   fifo_long #(.WIDTH(WIDTH),.SIZE(SIZE)) middle_fifo
     (.clk(clk),.reset(reset),.clear(clear),
      .datain(data_int), .src_rdy_i(src_rdy_1), .dst_rdy_o(dst_rdy_1),
      .dataout(data_int2), .src_rdy_o(src_rdy_2), .dst_rdy_i(dst_rdy_2),
      .space(l_space),.occupied(l_occupied) );
   
   fifo_short #(.WIDTH(WIDTH)) tail_fifo
     (.clk(clk),.reset(reset),.clear(clear),
      .datain(data_int2), .src_rdy_i(src_rdy_2), .dst_rdy_o(dst_rdy_2),
      .dataout(dataout), .src_rdy_o(src_rdy_o), .dst_rdy_i(dst_rdy_i),
      .space(s2_space),.occupied(s2_occupied) );
   
   assign 	    space = {11'b0,s1_space} + {11'b0,s2_space} + l_space;
   assign 	    occupied = {11'b0,s1_occupied} + {11'b0,s2_occupied} + l_occupied;
      
endmodule // cascadefifo2
module splitter36
    (
        input clk, input rst, input clr,
        input [35:0] inp_data, input inp_valid, output inp_ready,
        output [35:0] out0_data, output out0_valid, input out0_ready,
        output [35:0] out1_data, output out1_valid, input out1_ready
    );

    localparam STATE_COPY_BOTH = 0;
    localparam STATE_COPY_ZERO = 1;
    localparam STATE_COPY_ONE = 2;

    reg [1:0] state;
    reg [35:0] data_reg;

    assign out0_data = (state == STATE_COPY_BOTH)? inp_data : data_reg;
    assign out1_data = (state == STATE_COPY_BOTH)? inp_data : data_reg;

    assign out0_valid =
        (state == STATE_COPY_BOTH)? inp_valid : (
        (state == STATE_COPY_ZERO)? 1'b1      : (
    1'b0));

    assign out1_valid =
        (state == STATE_COPY_BOTH)? inp_valid : (
        (state == STATE_COPY_ONE)?  1'b1      : (
    1'b0));

    assign inp_ready = (state == STATE_COPY_BOTH)? (out0_ready | out1_ready) : 1'b0;

    always @(posedge clk)
    if (rst | clr) begin
        state <= STATE_COPY_BOTH;
    end
    else begin
        case (state)

        STATE_COPY_BOTH: begin
            if ((out0_valid & out0_ready) & ~(out1_valid & out1_ready)) begin
                state <= STATE_COPY_ONE;
            end
            else if (~(out0_valid & out0_ready) & (out1_valid & out1_ready)) begin
                state <= STATE_COPY_ZERO;
            end
            data_reg <= inp_data;
        end

        STATE_COPY_ZERO: begin
            if (out0_valid & out0_ready) begin
                state <= STATE_COPY_BOTH;
            end
        end

        STATE_COPY_ONE: begin
            if (out1_valid & out1_ready) begin
                state <= STATE_COPY_BOTH;
            end
        end

        endcase //state
    end



endmodule //splitter36
module packet_tb();

   wire [7:0] data;
   wire       sof, eof, src_rdy, dst_rdy;

   wire       clear = 0;
   reg 	      clk = 0;
   reg 	      reset = 1;

   always #10 clk <= ~clk;
   initial #1000 reset <= 0;

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

   wire [31:0] total, crc_err, seq_err, len_err;
   
   packet_generator pkt_gen (.clk(clk), .reset(reset), .clear(clear),
			     .data_o(data), .sof_o(sof), .eof_o(eof),
			     .src_rdy_o(src_rdy), .dst_rdy_i(dst_rdy));

   packet_verifier pkt_ver (.clk(clk), .reset(reset), .clear(clear),
			    .data_i(data), .sof_i(sof), .eof_i(eof),
			    .src_rdy_i(src_rdy), .dst_rdy_o(dst_rdy),
			    .total(total), .crc_err(crc_err), .seq_err(seq_err), .len_err(len_err));

endmodule // packet_tb
module fifo_tb();
   
   reg clk = 0;
   reg rst = 1;
   reg clear = 0;
   initial #1000 rst = 0;
   always #50 clk = ~clk;
   
   reg [31:0] f36_data = 0;
   reg [1:0] f36_occ = 0;
   reg f36_sof = 0, f36_eof = 0;
   reg f36_src_rdy;
   wire f36_dst_rdy;
   
   wire [7:0] ll_data;
   wire ll_src_rdy, ll_dst_rdy, ll_sof, ll_eof;
   wire [35:0] err_dat;
   wire        err_src_rdy, err_dst_rdy;

   fifo36_to_ll8 fifo36_to_ll8
     (.clk(clk),.reset(rst),.clear(clear),
      .f36_data({f36_occ,f36_eof,f36_sof,f36_data}),.f36_src_rdy_i(f36_src_rdy),.f36_dst_rdy_o(f36_dst_rdy),
      .ll_data(ll_data),.ll_sof(ll_sof),.ll_eof(ll_eof),
      .ll_src_rdy(ll_src_rdy),.ll_dst_rdy(ll_dst_rdy));

   assign ll_dst_rdy = 1;
   
   always @(posedge clk)
     if(ll_src_rdy)
       $display("LL: SOF %d, EOF %d, DAT %x",ll_sof,ll_eof,ll_data);
   
   initial $dumpfile("fifo_tb.vcd");
   initial $dumpvars(0,fifo_tb);

   initial
     begin
	@(negedge rst);
	@(posedge clk);
	@(posedge clk);
	@(posedge clk);
	@(posedge clk);
	f36_src_rdy <= 1;
	{f36_occ,f36_eof,f36_sof,f36_data} <= { 2'b00,1'b0,1'b1,32'h00010203};
	@(posedge clk);
	{f36_occ,f36_eof,f36_sof,f36_data} <= { 2'b00,1'b0,1'b0,32'h04050607};
	@(posedge clk);
	{f36_occ,f36_eof,f36_sof,f36_data} <= { 2'b00,1'b0,1'b0,32'h08090a0b};
	@(posedge clk);
	{f36_occ,f36_eof,f36_sof,f36_data} <= { 2'b11,1'b1,1'b0,32'h0c0d0e0f};
	@(posedge clk);
	f36_src_rdy <= 0;
     end
   
   initial #4000 $finish;
endmodule // longfifo_tb
module packet_generator
  (input clk, input reset, input clear,
   output reg [7:0] data_o, output sof_o, output eof_o,
   input [127:0] header,
   output src_rdy_o, input dst_rdy_i);

   localparam len = 32'd2000;

   reg [31:0] state;
   reg [31:0] seq;
   reg [31:0] crc_out;
   wire        calc_crc = src_rdy_o & dst_rdy_i & ~(state[31:2] == 30'h3FFF_FFFF);
   
	
   always @(posedge clk)
     if(reset | clear)
       seq <= 0;
     else
       if(eof_o & src_rdy_o & dst_rdy_i)
	 seq <= seq + 1;
   
   always @(posedge clk)
     if(reset | clear)
       state <= 0;
     else
       if(src_rdy_o & dst_rdy_i)
	 if(state == (len - 1))
	   state <= 32'hFFFF_FFFC;
	 else
	   state <= state + 1;

   always @*
     case(state)
       0 :   data_o <= len[31:24];
       1 :   data_o <= len[23:16];
       2 :   data_o <= len[15:8];
       3 :   data_o <= len[7:0];
       4 :   data_o <= seq[31:24];
       5 :   data_o <= seq[23:16];
       6 :   data_o <= seq[15:8];
       7 :   data_o <= seq[7:0];
       8 :   data_o <= header[7:0];
       9 :   data_o <= header[15:8];
       10 :  data_o <= header[23:16];
       11 :  data_o <= header[31:24];
       12 :  data_o <= header[39:32];
       13 :  data_o <= header[47:40];
       14 :  data_o <= header[55:48];
       15 :  data_o <= header[63:56];
       16 :  data_o <= header[71:64];
       17 :  data_o <= header[79:72];
       18 :  data_o <= header[87:80];
       19 :  data_o <= header[95:88];
       20 :  data_o <= header[103:96];
       21 :  data_o <= header[111:104];
       22 :  data_o <= header[119:112];
       23 :  data_o <= header[127:120];

       32'hFFFF_FFFC : data_o <= crc_out[31:24];
       32'hFFFF_FFFD : data_o <= crc_out[23:16];
       32'hFFFF_FFFE : data_o <= crc_out[15:8];
       32'hFFFF_FFFF : data_o <= crc_out[7:0];
       default : data_o <= state[7:0];
     endcase // case (state)
   
   assign src_rdy_o = 1;
   assign sof_o = (state == 0);
   assign eof_o = (state == 32'hFFFF_FFFF);

   wire        clear_crc = eof_o & src_rdy_o & dst_rdy_i;
   
//   crc crc(.clk(clk), .reset(reset), .clear(clear_crc), .data(data_o), 
//	   .calc(calc_crc), .crc_out(crc_out), .match());
   always @(posedge clk)
     if(reset | clear | clear_crc)
       crc_out <= 0;
     else
       if(calc_crc)
	 crc_out <= crc_out + data_o;
   
endmodule // packet_generator
module ll8_to_fifo36
  (input clk, input reset, input clear,
   input [7:0] ll_data,
   input ll_sof_n,
   input ll_eof_n,
   input ll_src_rdy_n,
   output ll_dst_rdy_n,

   output [35:0] f36_data,
   output f36_src_rdy_o,
   input f36_dst_rdy_i );

   wire f36_write    = f36_src_rdy_o & f36_dst_rdy_i;
      
   // Why anybody would use active low in an FPGA is beyond me...
   wire  ll_sof      = ~ll_sof_n;
   wire  ll_eof      = ~ll_eof_n;
   wire  ll_src_rdy  = ~ll_src_rdy_n;
   wire  ll_dst_rdy;
   assign    ll_dst_rdy_n = ~ll_dst_rdy;

   reg 	 f36_sof, f36_eof;
   reg [1:0] f36_occ;
   
   
   reg [2:0] state;
   reg [7:0] dat0, dat1, dat2, dat3;

   always @(posedge clk)
     if(ll_src_rdy & ((state==0)|f36_write))
       f36_sof <= ll_sof;

   always @(posedge clk)
     if(ll_src_rdy & ((state !=4)|f36_write))
       f36_eof <= ll_eof;

   always @(posedge clk)
     if(ll_eof)
       f36_occ <= state[1:0] + 1;
     else
       f36_occ <= 0;
   
   always @(posedge clk)
     if(reset)
       state   <= 0;
     else
       if(ll_src_rdy)
	 case(state)
	   0 : 
	     if(ll_eof)
	       state <= 4;
	     else
	       state <= 1;
	   1 : 
	     if(ll_eof)
	       state <= 4;
	     else
	       state <= 2;
	   2 : 
	     if(ll_eof)
	       state <= 4;
	     else 
	       state <= 3;
	   3 : state <= 4;
	   4 : 
	     if(f36_dst_rdy_i)
	       if(ll_eof)
		 state 	   <= 4;
	       else
		 state 	   <= 1;
	 endcase // case(state)
       else
	 if(f36_write)
	   state 	   <= 0;

   always @(posedge clk)
     if(ll_src_rdy & (state==3))
       dat3 		   <= ll_data;

   always @(posedge clk)
     if(ll_src_rdy & (state==2))
       dat2 		   <= ll_data;

   always @(posedge clk)
     if(ll_src_rdy & (state==1))
       dat1 		   <= ll_data;

   always @(posedge clk)
     if(ll_src_rdy & ((state==0) | f36_write))
       dat0 		   <= ll_data;
   
   assign    ll_dst_rdy     = f36_dst_rdy_i | (state != 4);
   assign    f36_data 	    = {f36_occ,f36_eof,f36_sof,dat0,dat1,dat2,dat3};  // FIXME endianess
   assign    f36_src_rdy_o  = (state == 4);
      
endmodule // ll8_to_fifo36
module fifo36_to_ll8
  (input clk, input reset, input clear,
   input [35:0] f36_data,
   input f36_src_rdy_i,
   output f36_dst_rdy_o,

   output [7:0] ll_data,
   output ll_sof,
   output ll_eof,
   output ll_src_rdy,
   input ll_dst_rdy,

   output [31:0] debug);

   // Shortfifo on input to guarantee no deadlock
   wire [35:0] 	 f36_data_int;
   wire 	 f36_src_rdy_int, f36_dst_rdy_int;
   reg [7:0] 	 ll_data_int;
   wire 	 ll_sof_int, ll_eof_int, ll_src_rdy_int, ll_dst_rdy_int;
   
   fifo_short #(.WIDTH(36)) head_fifo
     (.clk(clk),.reset(reset),.clear(clear),
      .datain(f36_data), .src_rdy_i(f36_src_rdy_i), .dst_rdy_o(f36_dst_rdy_o),
      .dataout(f36_data_int), .src_rdy_o(f36_src_rdy_int), .dst_rdy_i(f36_dst_rdy_int),
      .space(),.occupied() );

   // Actual fifo36 to ll8, can deadlock if not connected to shortfifo
   wire [1:0] 	 f36_occ_int = f36_data_int[35:34];
   wire 	 f36_sof_int = f36_data_int[32];
   wire 	 f36_eof_int = f36_data_int[33];
   wire 	 advance, end_early;
   reg [1:0] 	 state;
   
   assign debug    = {29'b0,state};

   always @(posedge clk)
     if(reset)
       state 	  <= 0;
     else
       if(advance)
	 if(ll_eof_int)
	   state  <= 0;
	 else
	   state  <= state + 1;

   always @*
     case(state)
       0 : ll_data_int = f36_data_int[31:24];
       1 : ll_data_int = f36_data_int[23:16];
       2 : ll_data_int = f36_data_int[15:8];
       3 : ll_data_int = f36_data_int[7:0];
       default : ll_data_int = f36_data_int[31:24];
       endcase // case (state)
   
   assign ll_sof_int 	 = (state==0) & f36_sof_int;
   assign ll_eof_int 	 = f36_eof_int & (((state==0)&(f36_occ_int==1)) |
					  ((state==1)&(f36_occ_int==2)) |
					  ((state==2)&(f36_occ_int==3)) |
					  (state==3));
   
   assign ll_src_rdy_int = f36_src_rdy_int;
   
   assign advance 	 = ll_src_rdy_int & ll_dst_rdy_int;
   assign f36_dst_rdy_int= advance & ((state==3)|ll_eof_int);

   // Short FIFO on output to guarantee no deadlock
   ll8_shortfifo tail_fifo
     (.clk(clk), .reset(reset), .clear(clear),
      .datain(ll_data_int), .sof_i(ll_sof_int), .eof_i(ll_eof_int),
      .error_i(0), .src_rdy_i(ll_src_rdy_int), .dst_rdy_o(ll_dst_rdy_int),
      .dataout(ll_data), .sof_o(ll_sof), .eof_o(ll_eof),
      .error_o(), .src_rdy_o(ll_src_rdy), .dst_rdy_i(ll_dst_rdy));

endmodule // fifo36_to_ll8
module fifo36_demux
  #(parameter match_data = 0,
    parameter match_mask = 0)
   (input clk, input reset, input clear,
    input [35:0] data_i, input src_rdy_i, output dst_rdy_o,
    output [35:0] data0_o, output src0_rdy_o, input dst0_rdy_i,
    output [35:0] data1_o, output src1_rdy_o, input dst1_rdy_i);

   localparam DMX_IDLE = 0;
   localparam DMX_DATA0 = 1;
   localparam DMX_DATA1 = 2;
   
   reg [1:0] 	  state;

   wire 	  match = |( (data_i ^ match_data) & match_mask );
   wire 	  eof = data_i[33];
   
   always @(posedge clk)
     if(reset | clear)
       state <= DMX_IDLE;
     else
       case(state)
	 DMX_IDLE :
	   if(src_rdy_i)
	     if(match)
	       state <= DMX_DATA1;
	     else
	       state <= DMX_DATA0;
	 DMX_DATA0 :
	   if(src_rdy_i & dst0_rdy_i & eof)
	     state <= DMX_IDLE;
	 DMX_DATA1 :
	   if(src_rdy_i & dst1_rdy_i & eof)
	     state <= DMX_IDLE;
	 default :
	   state <= DMX_IDLE;
       endcase // case (state)

   assign dst_rdy_o = (state==DMX_IDLE) ? 0 : (state==DMX_DATA0) ? dst0_rdy_i : dst1_rdy_i;
   assign src0_rdy_o = (state==DMX_DATA0) ? src_rdy_i : 0;
   assign src1_rdy_o = (state==DMX_DATA1) ? src_rdy_i : 0;

   assign data0_o = data_i;
   assign data1_o = data_i;
   
endmodule // fifo36_demux
module fifo_long
  #(parameter WIDTH=32, SIZE=9)
   (input clk, input reset, input clear,
    input [WIDTH-1:0] datain,
    input src_rdy_i,
    output dst_rdy_o,
    output [WIDTH-1:0] dataout,
    output src_rdy_o,
    input dst_rdy_i,
    
    output reg [15:0] space,
    output reg [15:0] occupied);
   
   wire write 	     = src_rdy_i & dst_rdy_o;
   wire read 	     = dst_rdy_i & src_rdy_o;
   wire full, empty;
   
   assign dst_rdy_o  = ~full;
   assign src_rdy_o  = ~empty;
   
   // Read side states
   localparam 	  EMPTY = 0;
   localparam 	  PRE_READ = 1;
   localparam 	  READING = 2;

   reg [SIZE-1:0] wr_addr, rd_addr;
   reg [1:0] 	  read_state;

   reg 	  empty_reg, full_reg;
   always @(posedge clk)
     if(reset)
       wr_addr <= 0;
     else if(clear)
       wr_addr <= 0;
     else if(write)
       wr_addr <= wr_addr + 1;

   ram_2port #(.DWIDTH(WIDTH),.AWIDTH(SIZE))
     ram (.clka(clk),
	  .ena(1'b1),
	  .wea(write),
	  .addra(wr_addr),
	  .dia(datain),
	  .doa(),

	  .clkb(clk),
	  .enb((read_state==PRE_READ)|read),
	  .web(0),
	  .addrb(rd_addr),
	  .dib({WIDTH{1'b1}}),
	  .dob(dataout));

   always @(posedge clk)
     if(reset)
       begin
	  read_state <= EMPTY;
	  rd_addr <= 0;
	  empty_reg <= 1;
       end
     else
       if(clear)
	 begin
	    read_state <= EMPTY;
	    rd_addr <= 0;
	    empty_reg <= 1;
	 end
       else 
	 case(read_state)
	   EMPTY :
	     if(write)
	       begin
		  //rd_addr <= wr_addr;
		  read_state <= PRE_READ;
	       end
	   PRE_READ :
	     begin
		read_state <= READING;
		empty_reg <= 0;
		rd_addr <= rd_addr + 1;
	     end
	   
	   READING :
	     if(read)
	       if(rd_addr == wr_addr)
		 begin
		    empty_reg <= 1;
		    if(write)
		      read_state <= PRE_READ;
		    else
		      read_state <= EMPTY;
		 end
	       else
		 rd_addr <= rd_addr + 1;
	 endcase // case(read_state)

   wire [SIZE-1:0] dont_write_past_me = rd_addr - 3;
   wire 	   becoming_full = wr_addr == dont_write_past_me;
     
   always @(posedge clk)
     if(reset)
       full_reg <= 0;
     else if(clear)
       full_reg <= 0;
     else if(read & ~write)
       full_reg <= 0;
     //else if(write & ~read & (wr_addr == (rd_addr-3)))
     else if(write & ~read & becoming_full)
       full_reg <= 1;

   //assign empty = (read_state != READING);
   assign empty = empty_reg;

   // assign full = ((rd_addr - 1) == wr_addr);
   assign full = full_reg;

   //////////////////////////////////////////////
   // space and occupied are for diagnostics only
   // not guaranteed exact

   localparam NUMLINES = (1<<SIZE)-2;
   always @(posedge clk)
     if(reset)
       space <= NUMLINES;
     else if(clear)
       space <= NUMLINES;
     else if(read & ~write)
       space <= space + 1;
     else if(write & ~read)
       space <= space - 1;
   
   always @(posedge clk)
     if(reset)
       occupied <= 0;
     else if(clear)
       occupied <= 0;
     else if(read & ~write)
       occupied <= occupied - 1;
     else if(write & ~read)
       occupied <= occupied + 1;
   
endmodule // fifo_long
module add_routing_header
  #(parameter PORT_SEL = 0,
    parameter PROT_ENG_FLAGS = 1)
   (input clk, input reset, input clear,
    input [35:0] data_i, input src_rdy_i, output dst_rdy_o,
    output [35:0] data_o, output src_rdy_o, input dst_rdy_i);

   reg [1:0] 	  line;
   wire [1:0] 	  port_sel_bits = PORT_SEL;
   wire [15:0] 	  len = data_i[15:0];
   
   always @(posedge clk)
     if(reset)
       line <= PROT_ENG_FLAGS ? 0 : 1;
     else
       if(src_rdy_o & dst_rdy_i)
	 if(data_o[33])
	   line <= PROT_ENG_FLAGS ? 0 : 1;
	 else
	   if(line != 3)
	     line <= line + 1;

   assign data_o = (line == 0) ? {4'b0001, 13'b0, port_sel_bits, 1'b1, len[13:0],2'b00} :
		   (line == 1) ? {3'b000, (PROT_ENG_FLAGS ? 1'b0: 1'b1), data_i[31:0]} : 
		   data_i[35:0];

   assign dst_rdy_o = dst_rdy_i & (line != 0);
   assign src_rdy_o = src_rdy_i;
   
endmodule // add_routing_header