dakies/OSS_Verilog huggingface dataset:
module reset_sync (
  // clock for the output reset
  input  clk,
  // glitch-free input reset
  input  reset_in,
  // output reset in the clk domain
  output reset_out);

  synchronizer #(
    // The input reset is async to the output clk domain... so timing should not be
    // analyzed here!
    .FALSE_PATH_TO_IN(1),
    // Assert reset_out by default. When clk starts toggling the downstream logic will
    // be in reset for at least 10 clk cycles. This allows the clock to settle (if needed)
    // and the reset to propagate fully to all logic.
    .INITIAL_VAL(1),
    .STAGES(10)
  ) reset_double_sync (
    .clk(clk), .rst(1'b0), .in(reset_in), .out(reset_out)
  );

endmodule // reset_sync
module axi_setting_reg #(
  parameter ADDR = 0,
  parameter USE_ADDR_LAST = 0,
  parameter ADDR_LAST = ADDR+1,
  parameter AWIDTH = 8,
  parameter WIDTH = 32,
  parameter USE_FIFO = 0,
  parameter FIFO_SIZE = 5,
  parameter DATA_AT_RESET = 0,
  parameter VALID_AT_RESET = 0,
  parameter LAST_AT_RESET = 0,
  parameter STROBE_LAST = 0,
  parameter REPEATS = 0,
  parameter MSB_ALIGN = 0
)
(
  input clk, input reset, output reg error_stb,
  input set_stb, input [AWIDTH-1:0] set_addr, input [31:0] set_data,
  output [WIDTH-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready
);

  reg init;

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

  always @(posedge clk) begin
    if (reset) begin
      o_tdata_int <= DATA_AT_RESET;
      o_tvalid_int <= VALID_AT_RESET;
      o_tlast_int <= LAST_AT_RESET;
      init <= 1'b0;
      error_stb <= 1'b0;
    end else begin
      error_stb <= 1'b0;
      if (o_tvalid_int & o_tready_int) begin
        // Deassert tvalid / tlast only if not repeating the output
        if (REPEATS == 0) begin
          o_tvalid_int <= 1'b0;
        end
        if ((REPEATS == 0) | (STROBE_LAST == 1)) begin
          o_tlast_int <= 1'b0;
        end
      end
      if (set_stb & ((ADDR[AWIDTH-1:0] == set_addr) | (USE_ADDR_LAST & (ADDR_LAST[AWIDTH-1:0] == set_addr)))) begin
        init <= 1'b1;
        o_tdata_int <= (MSB_ALIGN == 0) ? set_data[WIDTH-1:0] : set_data[31:32-WIDTH];
        o_tvalid_int <= 1'b1;
        if (set_stb & (STROBE_LAST | (USE_ADDR_LAST & (ADDR_LAST[AWIDTH-1:0] == set_addr)))) begin
          o_tlast_int <= 1'b1;
        end else begin
          o_tlast_int <= 1'b0;
        end
        if (~o_tready_int) begin
          error_stb <= 1'b1;
        end
      end
    end
  end

  generate
    if (USE_FIFO) begin
      axi_fifo #(
        .WIDTH(WIDTH+1), .SIZE(FIFO_SIZE))
      axi_fifo (
        .clk(clk), .reset(reset), .clear(1'b0),
        .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 else 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
  endgenerate

endmodule
module axi_test_vfifo
  #(parameter PACKET_SIZE = 128)
   (
    input aclk,
    input aresetn,
    input enable,
    // AXI Stream Out
    output reg out_axis_tvalid,
    input out_axis_tready,
    output [63 : 0] out_axis_tdata,
    output reg [7 : 0] out_axis_tstrb,
    output reg [7 : 0] out_axis_tkeep,
    output reg out_axis_tlast,
    output reg [0 : 0] out_axis_tid,
    output reg [0 : 0] out_axis_tdest,
    input vfifo_full,
    // AXI Stream In
    input in_axis_tvalid,
    output reg in_axis_tready,
    input [63 : 0] in_axis_tdata,
    input [7 : 0] in_axis_tstrb,
    input [7 : 0] in_axis_tkeep,
    input in_axis_tlast,
    input [0 : 0] in_axis_tid,
    input [0 : 0] in_axis_tdest,
    // Flags
    output reg flag_error,
    output heartbeat_in,
    output heartbeat_out,
    output [31:0] expected_count
    );
   

   reg [31:0] 	  out_count;
   reg [31:0] 	  in_count;
   reg [63:0] 	  in_axis_tdata_reg;
   reg 		  in_data_valid;
   


   //
   // Output 
   //
   always @(posedge aclk)
     if (!aresetn) begin
	out_count <= 0;
	out_axis_tvalid <= 0;
	out_axis_tid <= 0; // Don't care.
	out_axis_tdest <= 0; // Only use port 0 of VFIFO.
	out_axis_tstrb <= 0;  // Unused in VFIFO
	out_axis_tkeep <= 8'hFF; // Always use every byte of data
	out_axis_tlast <= 1'b0;
     end else if (enable) begin
	if (~vfifo_full) begin
	   // Always ready to output new count value.
	   out_axis_tvalid <= 1;
	   if (out_axis_tready) 
	     out_count <= out_count + 1;
	   // Assert TLAST every PACKET_SIZE beats.
	   if (out_count[15:0] == PACKET_SIZE)
	     out_axis_tlast <= 1'b1;
	   else
	     out_axis_tlast <= 1'b0;
	end else begin
	   out_axis_tvalid <= 0;
	end
     end else begin
	out_axis_tlast <= 1'b0;	
	out_axis_tvalid <= 0;
     end

   assign out_axis_tdata = {out_count,out_count};

   assign heartbeat_out = out_count[28];
   

   //
   // Input (Ignore TLAST signal)
   //
   always @(posedge aclk)
     if (!aresetn) begin
	in_axis_tready <= 0;
	in_axis_tdata_reg <= 0;
	in_data_valid <= 0;
	
     end else if (enable) begin
	in_axis_tready <= 1;
	in_axis_tdata_reg <= in_axis_tdata;
	if (in_axis_tvalid) 
	  in_data_valid <= 1;
	else
	  in_data_valid <= 0;
     end else begin
	in_data_valid <= 0;
	in_axis_tready <= 0;
     end // else: !if(enable)
   
   	  
   assign heartbeat_in = in_count[28];
   
   //
   // Input Checker
   //
   always @(posedge aclk)
     if (!aresetn) begin
	in_count <= 0;
	flag_error <= 0;
     end else if (enable) begin
	if (in_data_valid) begin
	   
	   if ((in_axis_tdata_reg[63:32] != in_count) || (in_axis_tdata_reg[31:0] != in_count))
	     begin
		flag_error <= 1;
		in_count <= in_axis_tdata_reg[63:32] + 1;
	     end
	   else
	     begin
		flag_error <= 0;
		in_count <= in_count + 1;
	     end
	   
	end
     end

   assign expected_count = in_count;
   

endmodule // axi_test_vfifo
module pulse_stretch #(
  parameter SCALE = 64'd12_500_000
)(
  input clk,
  input rst,
  input pulse,
  output pulse_stretched
);

  reg [$clog2(SCALE)-1:0] count = 'd0;
  reg             state = 1'b0;

  always @ (posedge clk)
    if (rst) begin
      state <= 1'b0;
      count <= 'd0;
    end
    else begin
      case (state)

      1'b0: begin
        if (pulse) begin
          state <= 1'b1;
          count <= 'd0;
        end
      end

      1'b1: begin
        if (count == SCALE)
          state <= 1'b0;
        else
          count <= count + 1'b1;
      end
      endcase
    end

  assign pulse_stretched = (state == 1'b1);

endmodule
module synchronizer #(
   parameter WIDTH            = 1,
   parameter STAGES           = 2,
   parameter INITIAL_VAL      = 0,
   parameter FALSE_PATH_TO_IN = 1
)(
   input              clk,
   input              rst,
   input  [WIDTH-1:0] in,
   output [WIDTH-1:0] out
);

   //Q: Why do we have a separate impl and instantiate
   //it with a different instance name based on this
   //arbitrary parameter FALSE_PATH_TO_IN?
   //A: To make constraining these synchronizers easier.
   //We would like to write a single false path constraint
   //for all synchronizers when the input is truly async.
   //However other cases might require constraining the input
   //of this module.
   //To enable this, all clients that hook up async signals to
   //the "in" port can set FALSE_PATH_TO_IN=1 (or use the default)
   //and all clients that want the "in" delay to be constrained can
   //set FALSE_PATH_TO_IN=0.
   //In the XDC we can write the following async constraint:
   //set_false_path -to [get_pins */synchronizer_false_path/stages[0].value_reg[0]/D]
   //and this will take care of all instances of this module with FALSE_PATH_TO_IN==1

   generate if (FALSE_PATH_TO_IN == 1) begin
      synchronizer_impl #(
        .WIDTH(WIDTH), .STAGES(STAGES), .INITIAL_VAL(INITIAL_VAL)
      ) synchronizer_false_path (
         .clk(clk), .rst(rst), .in(in), .out(out)
      );
   end else begin
      synchronizer_impl #(
        .WIDTH(WIDTH), .STAGES(STAGES), .INITIAL_VAL(INITIAL_VAL)
      ) synchronizer_constrained (
         .clk(clk), .rst(rst), .in(in), .out(out)
      );
   end endgenerate

endmodule   //synchronizer
module rxmac_to_ll8
  (input clk, input reset, input clear,
   input [7:0] rx_data, input rx_valid, input rx_error, input rx_ack,
   output [7:0] ll_data, output ll_sof, output ll_eof, output ll_error, output ll_src_rdy, input ll_dst_rdy );

   reg [2:0] xfer_state;

   localparam XFER_IDLE     = 0;
   localparam XFER_ACTIVE   = 1;
   localparam XFER_ERROR    = 2;
   localparam XFER_ERROR2   = 3;
   localparam XFER_OVERRUN  = 4;
   localparam XFER_OVERRUN2 = 5;
      
   assign ll_data 	    = rx_data;
   assign ll_src_rdy 	    = ((rx_valid & (xfer_state != XFER_OVERRUN2) )
			       | (xfer_state == XFER_ERROR) 
			       | (xfer_state == XFER_OVERRUN));
   assign ll_sof 	    = ((xfer_state==XFER_IDLE)|(xfer_state==XFER_ERROR)|(xfer_state==XFER_OVERRUN));
   assign ll_eof 	    = (rx_ack | (xfer_state==XFER_ERROR) | (xfer_state==XFER_OVERRUN));
   assign ll_error 	    = (xfer_state == XFER_ERROR)|(xfer_state==XFER_OVERRUN);
   
   always @(posedge clk)
     if(reset | clear)
       xfer_state 	   <= XFER_IDLE;
     else
       case(xfer_state)
	 XFER_IDLE :
	   if(rx_valid)
	     xfer_state <= XFER_ACTIVE;
	 XFER_ACTIVE :
	   if(rx_error)
	     xfer_state <= XFER_ERROR;
	   else if(~rx_valid)
	     xfer_state <= XFER_IDLE;
	   else if(~ll_dst_rdy)
	     xfer_state <= XFER_OVERRUN;
	 XFER_ERROR :
	   if(ll_dst_rdy)
	     xfer_state <= XFER_ERROR2;
	 XFER_ERROR2 :
	   if(~rx_error)
	     xfer_state <= XFER_IDLE;
	 XFER_OVERRUN :
	   if(ll_dst_rdy)
	     xfer_state <= XFER_OVERRUN2;
	 XFER_OVERRUN2 :
	   if(~rx_valid)
	     xfer_state <= XFER_IDLE;
       endcase // case (xfer_state)

   
endmodule // rxmac_to_ll8
module simple_gemac
  (input clk125, input reset,
   // GMII
   output GMII_GTX_CLK, output GMII_TX_EN, output GMII_TX_ER, output [7:0] GMII_TXD,
   input GMII_RX_CLK, input GMII_RX_DV, input GMII_RX_ER, input [7:0] GMII_RXD,

   // Flow Control Interface
   input pause_req, input [15:0] pause_time_req, input pause_respect_en,

   // Settings
   input [47:0] ucast_addr, input [47:0] mcast_addr,
   input pass_ucast, input pass_mcast, input pass_bcast, input pass_pause, input pass_all,
   
   // RX Client Interface
   output rx_clk, output [7:0] rx_data, output rx_valid, output rx_error, output rx_ack,

   // TX Client Interface
   output tx_clk, input [7:0] tx_data, input tx_valid, input tx_error, output tx_ack,

   output [31:0] debug
   );

   localparam SGE_IFG 		     = 8'd12;  // 12 should be the absolute minimum

   wire rst_rxclk, rst_txclk;   
   reset_sync reset_sync_tx (.clk(tx_clk),.reset_in(reset),.reset_out(rst_txclk));
   reset_sync reset_sync_rx (.clk(rx_clk),.reset_in(reset),.reset_out(rst_rxclk));

   wire [15:0] pause_quanta_rcvd;
   wire        pause_rcvd, pause_apply, paused;
   
   simple_gemac_tx simple_gemac_tx
     (.clk125(clk125),.reset(rst_txclk),
      .GMII_GTX_CLK(GMII_GTX_CLK), .GMII_TX_EN(GMII_TX_EN),
      .GMII_TX_ER(GMII_TX_ER), .GMII_TXD(GMII_TXD),
      .tx_clk(tx_clk), .tx_data(tx_data), .tx_valid(tx_valid), .tx_error(tx_error), .tx_ack(tx_ack),
      .ifg(SGE_IFG), .mac_addr(ucast_addr),
      .pause_req(pause_req), .pause_time(pause_time_req),  // We request flow control
      .pause_apply(pause_apply), .paused(paused)  // We respect flow control
      );

   simple_gemac_rx simple_gemac_rx
     (.reset(rst_rxclk),
      .GMII_RX_CLK(GMII_RX_CLK), .GMII_RX_DV(GMII_RX_DV), 
      .GMII_RX_ER(GMII_RX_ER), .GMII_RXD(GMII_RXD),
      .rx_clk(rx_clk), .rx_data(rx_data), .rx_valid(rx_valid), .rx_error(rx_error), .rx_ack(rx_ack),
      .ucast_addr(ucast_addr), .mcast_addr(mcast_addr),
      .pass_ucast(pass_ucast), .pass_mcast(pass_mcast), .pass_bcast(pass_bcast), 
      .pass_pause(pass_pause), .pass_all(pass_all),
      .pause_quanta_rcvd(pause_quanta_rcvd), .pause_rcvd(pause_rcvd),
      .debug(debug)
      );

   flow_ctrl_tx flow_ctrl_tx
     (.rst(rst_txclk), .tx_clk(tx_clk),
      .tx_pause_en(pause_respect_en),
      .pause_quanta(pause_quanta_rcvd), // 16 bit value
      .pause_quanta_val(pause_rcvd),
      .pause_apply(pause_apply),
      .paused(paused)
      );

endmodule // simple_gemac
module address_filter_promisc
  (input clk,
   input reset,
   input go,
   input [7:0] data,
   output match,
   output done);

   reg [2:0] af_state;

   always @(posedge clk)
     if(reset)
       af_state     <= 0;
     else
       if(go)
	 af_state <= 1;//(data[0] == 1'b0) ? 1 : 7;
       else
	 case(af_state)
	   1 : af_state <= 2;
	   2 : af_state <= 3;
	   3 : af_state <= 4;
	   4 : af_state <= 5;
	   5 : af_state <= 6;
	   6, 7 : af_state <= 0;
	 endcase // case (af_state)

   assign match  = (af_state==6);
   assign done 	 = (af_state==6)|(af_state==7);
   
endmodule // address_filter_promisc
module ll8_to_txmac
  (input clk, input reset, input clear,
   input [7:0] ll_data, input ll_eof, input ll_src_rdy, output ll_dst_rdy,
   output [7:0] tx_data, output tx_valid, output tx_error, input tx_ack );

   reg [2:0] xfer_state;

   localparam XFER_IDLE      = 0;
   localparam XFER_ACTIVE    = 1;
   localparam XFER_WAIT1     = 2;
   localparam XFER_UNDERRUN  = 3;
   localparam XFER_DROP      = 4;
   
   always @(posedge clk)
     if(reset | clear)
       xfer_state 	    <= XFER_IDLE;
     else
       case(xfer_state)
	 XFER_IDLE :
	   if(tx_ack)
	     xfer_state <= XFER_ACTIVE;
	 XFER_ACTIVE :
	   if(~ll_src_rdy)
	     xfer_state <= XFER_UNDERRUN;
	   else if(ll_eof)
	     xfer_state <= XFER_WAIT1;
	 XFER_WAIT1 :
	   xfer_state <= XFER_IDLE;
	 XFER_UNDERRUN :
	   xfer_state <= XFER_DROP;
	 XFER_DROP :
	   if(ll_eof)
	     xfer_state <= XFER_IDLE;
       endcase // case (xfer_state)

   assign ll_dst_rdy 	 = (xfer_state == XFER_ACTIVE) | tx_ack | (xfer_state == XFER_DROP);
   assign tx_valid 	 = (ll_src_rdy & (xfer_state == XFER_IDLE))|(xfer_state == XFER_ACTIVE);
   assign tx_data 	 = ll_data;
   assign tx_error 	 = (xfer_state == XFER_UNDERRUN);
   
endmodule // ll8_to_txmac
module axi64_to_ll8
  #(parameter START_BYTE=6)
   (input clk, input reset, input clear,
    input [63:0] axi64_tdata, input axi64_tlast, input [3:0] axi64_tuser, input axi64_tvalid, output axi64_tready,
    output [7:0] ll_data, output ll_eof, output ll_src_rdy, input ll_dst_rdy);

   reg [7:0] 	 data_int;
   wire 	 eof_int, valid_int, ready_int;

   reg [2:0] 	 state = START_BYTE;
   reg 		 eof, done;
   reg [3:0] 	 occ;

   wire [63:0] axi64_tdata_gated;
   wire        axi64_tlast_gated;
   wire [3:0]  axi64_tuser_gated;
   wire        axi64_tvalid_gated;
   wire        axi64_tready_gated;

   axi_packet_gate #(
     .WIDTH(68),
     .SIZE(10)
   ) axi64_packet_gater (
     .clk(clk), .reset(reset), .clear(clear),
     .i_tdata({axi64_tuser, axi64_tdata}), .i_tlast(axi64_tlast),
     .i_tvalid(axi64_tvalid), .i_tready(axi64_tready),
     .o_tdata({axi64_tuser_gated, axi64_tdata_gated}), .o_tlast(axi64_tlast_gated),
     .o_tvalid(axi64_tvalid_gated), .o_tready(axi64_tready_gated)
   );

   always @(posedge clk)
     if(reset | clear)
       state <= START_BYTE;
     else
       if(valid_int & ready_int)
	 if(eof_int)
	   state <= START_BYTE;
	 else
	   state <= state + 3'd1;

   assign valid_int = axi64_tvalid_gated;
   assign axi64_tready_gated = ready_int & (eof_int | state == 7);
   assign eof_int = axi64_tlast_gated & (axi64_tuser_gated[2:0] == (state + 3'd1));

   always @*
     case(state)
       0 : data_int <= axi64_tdata_gated[63:56];
       1 : data_int <= axi64_tdata_gated[55:48];
       2 : data_int <= axi64_tdata_gated[47:40];
       3 : data_int <= axi64_tdata_gated[39:32];
       4 : data_int <= axi64_tdata_gated[31:24];
       5 : data_int <= axi64_tdata_gated[23:16];
       6 : data_int <= axi64_tdata_gated[15:8];
       7 : data_int <= axi64_tdata_gated[7:0];
       default : data_int <= axi64_tdata_gated[7:0];
     endcase // case (state)

   axi_fifo_short #(.WIDTH(9)) ll8_fifo
     (.clk(clk), .reset(reset), .clear(0),
      .i_tdata({eof_int, data_int}), .i_tvalid(valid_int), .i_tready(ready_int),
      .o_tdata({ll_eof, ll_data}), .o_tvalid(ll_src_rdy), .o_tready(ll_dst_rdy),
      .space(), .occupied());

endmodule // axi64_to_ll8
module ll8_to_axi64
  #(parameter START_BYTE=6,
    parameter LABEL=8'h00)
   (input clk, input reset, input clear,
    input [7:0] ll_data, input ll_eof, input ll_error, input ll_src_rdy, output ll_dst_rdy,
    output [63:0] axi64_tdata, output axi64_tlast, output [3:0] axi64_tuser, output axi64_tvalid, input axi64_tready);

   wire 	  error_int, eof_int;
   wire [7:0] 	  data_int;
   wire 	  valid_int, ready_int;
   
   axi_fifo_short #(.WIDTH(10)) ll8_fifo
     (.clk(clk), .reset(reset), .clear(0),
      .i_tdata({ll_error, ll_eof, ll_data}), .i_tvalid(ll_src_rdy), .i_tready(ll_dst_rdy),
      .o_tdata({error_int, eof_int, data_int}), .o_tvalid(valid_int), .o_tready(ready_int),
      .space(), .occupied());

   wire [7:0] 	  label_wire = LABEL; // Enforces parameter width
   
   reg [3:0] 	  state = START_BYTE;
   reg [63:0] 	  holding; // = {label_wire, 56'h0};
   reg 		  err, eof, done;
   reg [3:0] 	  occ;

   localparam WAIT = 4'd8;
   
   always @(posedge clk)
     if(reset | clear)
       begin
	  state <= START_BYTE;
	  holding <= {label_wire, 56'h0};
	  err <= 1'b0;
	  eof <= 1'b0;
	  occ <= 3'd0;
	  done <= 1'b0;
       end
     else
       if(state == WAIT)
	 begin
	    state <= START_BYTE;
	    done <= 1'b0;
	    holding <= {label_wire, 56'h0};
	 end
       else if(valid_int & ready_int)
	 begin
	    case(state)
	      4'd0: 
		begin
		   holding[63:56] <= data_int;
		   holding[55:0] <= 56'h0;
		end
	      4'd1: holding[55:48] <= data_int;
	      4'd2: holding[47:40] <= data_int;
	      4'd3: holding[39:32] <= data_int;
	      4'd4: holding[31:24] <= data_int;
	      4'd5: holding[23:16] <= data_int;
	      4'd6: holding[15:8] <= data_int;
	      4'd7: holding[7:0] <= data_int;
	    endcase // case (state)
	    
	    err <= error_int;
	    eof <= eof_int;
            if(error_int | eof_int)
	      begin
		 occ <= state+1;
		 done <= 1'b1;
		 state <= WAIT;
	      end
	    else if (state == 4'd7)
	      begin
		 occ <= 3'd0;
		 done <= 1'b1;
		 state <= 4'd0;
	      end
	    else
	      begin
		 occ <= 3'd0;
		 done <= 1'b0;
		 state <= state + 4'd1;
	      end // else: !if(state == 4'd7)
	    
	 end // if (valid_int & ready_int)
       else
	 done <= 1'b0;
   
   assign axi64_tdata = holding;
   assign axi64_tlast = eof;
   assign axi64_tuser[3] = err;
   assign axi64_tuser[2:0] = occ;

   assign ready_int = axi64_tready & (state != WAIT);
   assign axi64_tvalid = done;
   		  
endmodule // ll8_to_axi64
module flow_ctrl_rx
  (input pause_request_en, input [15:0] pause_time, input [15:0] pause_thresh,
   input rx_clk, input rx_reset, input [15:0] rx_fifo_space,
   input tx_clk, input tx_reset, output reg pause_req, output reg [15:0] pause_time_req
   );
   
   // ******************************************************************************        
   // Force our TX to send a PAUSE frame because our RX is nearly full
   // ******************************************************************************

   // RX Clock Domain
   reg xon, xoff;
   reg [21:0] countdown;

   wire [15:0] pause_low_thresh = pause_thresh;
   wire [15:0] pause_hi_thresh = 16'hFFFF;
   wire [21:0] pq_reduced = {pause_time,6'd0} - 1700;
   
   always @(posedge rx_clk)
     if(rx_reset)
       xoff <= 0;
     else
       xoff <= (pause_request_en & (countdown==0) & (rx_fifo_space < pause_low_thresh));
   
   always @(posedge rx_clk)
     if(rx_reset)
       xon  <= 0;
     else
       xon  <= ((countdown!=0) & (rx_fifo_space > pause_hi_thresh));
   
   always @(posedge rx_clk)
     if(rx_reset)
       countdown <= 0;
     else if(xoff)
       countdown <= pq_reduced;
     else if(xon)
       countdown <= 0;
     else if(countdown != 0)
       countdown <= countdown - 1;

   // Cross clock domains
   wire        xon_tx, xoff_tx;
   oneshot_2clk send_xon (.clk_in(rx_clk), .in(xon), .clk_out(tx_clk), .out(xon_tx));
   oneshot_2clk send_xoff (.clk_in(rx_clk), .in(xoff), .clk_out(tx_clk), .out(xoff_tx));
   
   always @(posedge tx_clk)
     if(xoff_tx)
       pause_time_req <= pause_time;
     else if(xon_tx)
       pause_time_req <= 0;

   always @(posedge tx_clk)
     if(tx_reset)
       pause_req      <= 0;
     else 
       pause_req      <= xon_tx | xoff_tx;
   
endmodule // flow_ctrl_rx
module flow_ctrl_tx
  (input        rst,
   input        tx_clk,
   //host processor
   input        tx_pause_en,
   // From MAC_rx_ctrl
   input [15:0] pause_quanta,
   input        pause_quanta_val,
   // MAC_tx_ctrl
   output       pause_apply,
   input        paused);
     
   // ******************************************************************************        
   // Inhibit our TX from transmitting because they sent us a PAUSE frame
   // ******************************************************************************

   // Pauses are in units of 512 bit times, or 64 bytes/clock cycles, and can be
   //   as big as 16 bits, so 22 bits are needed for the counter
   
   reg [15+6:0] pause_quanta_counter;
   reg 		pqval_d1, pqval_d2;		

   always @(posedge tx_clk) pqval_d1 <= pause_quanta_val;
   always @(posedge tx_clk) pqval_d2 <= pqval_d1;

   always @ (posedge tx_clk or posedge rst)
     if (rst)
       pause_quanta_counter <= 0;
     else if (pqval_d1 & ~pqval_d2)
       pause_quanta_counter <= {pause_quanta, 6'b0}; 
     else if((pause_quanta_counter!=0) & paused)
       pause_quanta_counter <= pause_quanta_counter - 1;

   assign	pause_apply = tx_pause_en & (pause_quanta_counter != 0);
   
endmodule // flow_ctrl
module crc
  (input clk, 
   input reset,
   input clear, 
   input [7:0] data,
   input calc,
   output [31:0] crc_out,
   output match);
   
   function[31:0]  NextCRC;
      input[7:0]      D;
      input[31:0]     C;
      reg[31:0]       NewCRC;
      begin
	 NewCRC[0]   = C[24]^C[30]^D[1]^D[7];
	 NewCRC[1]   = C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7];
	 NewCRC[2]   = C[26]^D[5]^C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7];
	 NewCRC[3]   = C[27]^D[4]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6];
	 NewCRC[4]   = C[28]^D[3]^C[27]^D[4]^C[26]^D[5]^C[24]^C[30]^D[1]^D[7];
	 NewCRC[5]   = C[29]^D[2]^C[28]^D[3]^C[27]^D[4]^C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7];
	 NewCRC[6]   = C[30]^D[1]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6];
	 NewCRC[7]   = C[31]^D[0]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[24]^D[7];
	 NewCRC[8]   = C[0]^C[28]^D[3]^C[27]^D[4]^C[25]^D[6]^C[24]^D[7];
	 NewCRC[9]   = C[1]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^D[6];
	 NewCRC[10]  = C[2]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[24]^D[7];
	 NewCRC[11]  = C[3]^C[28]^D[3]^C[27]^D[4]^C[25]^D[6]^C[24]^D[7];
	 NewCRC[12]  = C[4]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^D[6]^C[24]^C[30]^D[1]^D[7];
	 NewCRC[13]  = C[5]^C[30]^D[1]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6];
	 NewCRC[14]  = C[6]^C[31]^D[0]^C[30]^D[1]^C[28]^D[3]^C[27]^D[4]^C[26]^D[5];
	 NewCRC[15]  = C[7]^C[31]^D[0]^C[29]^D[2]^C[28]^D[3]^C[27]^D[4];
	 NewCRC[16]  = C[8]^C[29]^D[2]^C[28]^D[3]^C[24]^D[7];
	 NewCRC[17]  = C[9]^C[30]^D[1]^C[29]^D[2]^C[25]^D[6];
	 NewCRC[18]  = C[10]^C[31]^D[0]^C[30]^D[1]^C[26]^D[5];
	 NewCRC[19]  = C[11]^C[31]^D[0]^C[27]^D[4];
	 NewCRC[20]  = C[12]^C[28]^D[3];
	 NewCRC[21]  = C[13]^C[29]^D[2];
	 NewCRC[22]  = C[14]^C[24]^D[7];
	 NewCRC[23]  = C[15]^C[25]^D[6]^C[24]^C[30]^D[1]^D[7];
	 NewCRC[24]  = C[16]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6];
	 NewCRC[25]  = C[17]^C[27]^D[4]^C[26]^D[5];
	 NewCRC[26]  = C[18]^C[28]^D[3]^C[27]^D[4]^C[24]^C[30]^D[1]^D[7];
	 NewCRC[27]  = C[19]^C[29]^D[2]^C[28]^D[3]^C[25]^C[31]^D[0]^D[6];
	 NewCRC[28]  = C[20]^C[30]^D[1]^C[29]^D[2]^C[26]^D[5];
	 NewCRC[29]  = C[21]^C[31]^D[0]^C[30]^D[1]^C[27]^D[4];
	 NewCRC[30]  = C[22]^C[31]^D[0]^C[28]^D[3];
	 NewCRC[31]  = C[23]^C[29]^D[2];
	 NextCRC     = NewCRC;
      end
   endfunction

   reg [31:0] crc_reg;
   always @ (posedge clk)
     if (reset | clear)
       crc_reg 	    <= 32'hffffffff;
     else if (calc)
       crc_reg 	    <= NextCRC(data,crc_reg);
        
   assign crc_out    = ~{crc_reg[24],crc_reg[25],crc_reg[26],crc_reg[27],crc_reg[28],crc_reg[29],crc_reg[30],crc_reg[31],
		      crc_reg[16],crc_reg[17],crc_reg[18],crc_reg[19],crc_reg[20],crc_reg[21],crc_reg[22],crc_reg[23],
		      crc_reg[8],crc_reg[9],crc_reg[10],crc_reg[11],crc_reg[12],crc_reg[13],crc_reg[14],crc_reg[15],
		      crc_reg[0],crc_reg[1],crc_reg[2],crc_reg[3],crc_reg[4],crc_reg[5],crc_reg[6],crc_reg[7] };

   assign match  = (crc_reg == 32'hc704_dd7b);
		    
endmodule // crc
module delay_line
  #(parameter WIDTH=32)
   (input clk,
    input [3:0] delay,
    input [WIDTH-1:0] din,
    output [WIDTH-1:0] dout);
    
   genvar 	       i;
   generate
      for (i=0;i<WIDTH;i=i+1)
	begin : gen_delay
	   SRL16E
	     srl16e(.Q(dout[i]),
		    .A0(delay[0]),.A1(delay[1]),.A2(delay[2]),.A3(delay[3]),
		    .CE(1),.CLK(clk),.D(din[i]));
	end
   endgenerate

endmodule // delay_line
module ll8_to_axi64_tb();

   reg clk    = 0;
   reg reset  = 1;
   
   always #10 clk = ~clk;
   
   initial $dumpfile("ll8_to_axi64_tb.vcd");
   initial $dumpvars(0,ll8_to_axi64_tb);

   initial
     begin
	#1000 reset = 0;
	#2000000;
	$finish;
     end
   
   wire [63:0]  tdata, tdata_int;
   wire [3:0] 	tuser, tuser_int;
   wire 	tlast, tlast_int;
   wire		tvalid, tvalid_int, tready, tready_int;

   reg [7:0] 	ll_data;
   reg 		ll_eof, ll_error, ll_src_rdy;
   wire 	ll_dst_rdy;

   wire [7:0] 	ll_data2;
   wire 	ll_eof2, ll_src_rdy2, ll_dst_rdy2;
   
   localparam RPT_COUNT = 12;
   
   initial
     begin
	ll_src_rdy <= 0;
 
	while(reset)
	  @(posedge clk);

	@(posedge clk);
	
	{ll_error, ll_eof, ll_data} <= { 1'b0, 1'b0, 8'hA0 };
	repeat(RPT_COUNT-1)
	  begin
	     ll_src_rdy <= 1;
	     @(posedge clk);
	     ll_data <= ll_data + 1;
	  end
	ll_eof <= 1;
	ll_data <= ll_data + 1;
	@(posedge clk);

	{ll_error, ll_eof, ll_data} <= { 1'b0, 1'b0, 8'hC0 };
	repeat(RPT_COUNT-1)
	  begin
	     ll_src_rdy <= 1;
	     @(posedge clk);
	     ll_data <= ll_data + 1;
	  end
	ll_eof <= 1; ll_error <= 1;
	ll_data <= ll_data + 1;
	@(posedge clk);
	ll_src_rdy <= 1'b0;

     end

   ll8_to_axi64 #(.START_BYTE(6), .LABEL(8'h89)) ll8_to_axi64
     (.clk(clk), .reset(reset), .clear(1'b0),
      .ll_data(ll_data), .ll_eof(ll_eof), .ll_error(ll_error), .ll_src_rdy(ll_src_rdy), .ll_dst_rdy(ll_dst_rdy),
      .axi64_tdata(tdata), .axi64_tlast(tlast), .axi64_tuser(tuser), .axi64_tvalid(tvalid), .axi64_tready(tready) );
   
   axi_fifo_short #(.WIDTH(69)) axi_fifo_short
     (.clk(clk), .reset(reset), .clear(1'b0),
      .i_tdata({tlast,tuser,tdata}), .i_tvalid(tvalid), .i_tready(tready),
      .o_tdata({tlast_int,tuser_int,tdata_int}), .o_tvalid(tvalid_int), .o_tready(tready_int));

   axi64_to_ll8 #(.START_BYTE(6)) axi64_to_ll8
     (.clk(clk), .reset(reset), .clear(1'b0),
      .axi64_tdata(tdata_int), .axi64_tlast(tlast_int), .axi64_tuser(tuser_int), .axi64_tvalid(tvalid_int), .axi64_tready(tready_int),
      .ll_data(ll_data2), .ll_eof(ll_eof2), .ll_src_rdy(ll_src_rdy2), .ll_dst_rdy(ll_dst_rdy2) );

   /*
   always @(posedge clk)
     if(ll_src_rdy2 & ll_dst_rdy2)
       $display("EOF %x\tDATA %x",ll_eof2, ll_data2);

   */
   assign ll_dst_rdy2 = 1;
   
   always @(posedge clk)
     if(tvalid_int & tready_int)
       $display("TERR %x\tTUSER %x\tTLAST %x\tTDATA %x",tuser_int[3],tuser_int[2:0], tlast_int, tdata_int);
   
endmodule // ll8_to_axi64_tb
module address_filter
  (input clk,
   input reset,
   input go,
   input [7:0] data,
   input [47:0] address,
   output match,
   output done);

   reg [2:0] af_state;

   always @(posedge clk)
     if(reset)
       af_state     <= 0;
     else
       if(go)
	 af_state <= (data == address[47:40]) ? 1 : 7;
       else
	 case(af_state)
	   1 : af_state <= (data == address[39:32]) ? 2 : 7;
	   2 : af_state <= (data == address[31:24]) ? 3 : 7;
	   3 : af_state <= (data == address[23:16]) ? 4 : 7;
	   4 : af_state <= (data == address[15:8])  ? 5 : 7;
	   5 : af_state <= (data == address[7:0]) ? 6 : 7;
	   6, 7 : af_state <= 0;
	 endcase // case (af_state)

   assign match  = (af_state==6);
   assign done 	 = (af_state==6)|(af_state==7);
   
endmodule // address_filter
module simple_uart_rx
    #(parameter SIZE=8)
    (input clk, input rst,
     output [7:0] fifo_out, input fifo_read, output [15:0] fifo_level, output fifo_empty,
     input [15:0] clkdiv, input rx);

   reg 		  rx_d1, rx_d2;
   always @(posedge clk)
     if(rst)
       {rx_d2,rx_d1} <= 0;
     else
       {rx_d2,rx_d1} <= {rx_d1,rx};

   reg [15:0] 	  baud_ctr;
   reg [3:0] 	  bit_ctr;
   reg [7:0] 	  sr;

   wire 	  neg_trans = rx_d2 & ~rx_d1;
   wire 	  shift_now = baud_ctr == (clkdiv>>1);
   wire 	  stop_now = (bit_ctr == 10) && shift_now;
   wire 	  go_now = (bit_ctr == 0) && neg_trans;

   always @(posedge clk)
     if(rst)
       sr <= 0;
     else if(shift_now)
       sr <= {rx_d2,sr[7:1]};

   always @(posedge clk)
     if(rst)
       baud_ctr <= 0;
     else
       if(go_now)
	 baud_ctr <= 1;
       else if(stop_now)
	 baud_ctr <= 0;
       else if(baud_ctr >= clkdiv)
	 baud_ctr <= 1;
       else if(baud_ctr != 0)
	 baud_ctr <= baud_ctr + 1;

   always @(posedge clk)
     if(rst)
       bit_ctr <= 0;
     else
       if(go_now)
	 bit_ctr <= 1;
       else if(stop_now)
	 bit_ctr <= 0;
       else if(baud_ctr == clkdiv)
	 bit_ctr <= bit_ctr + 1;

   wire 	  i_tready, o_tvalid;
   wire 	  full = ~i_tready;
   wire 	  write = ~full & stop_now;
   assign fifo_empty = ~o_tvalid;

   axi_fifo #(.WIDTH(8), .SIZE(SIZE)) fifo
     (.clk(clk),.reset(rst), .clear(1'b0),
      .i_tdata(sr),.i_tvalid(write),.i_tready(i_tready),
      .o_tdata(fifo_out),.o_tvalid(o_tvalid),.o_tready(fifo_read),
      .space(),.occupied(fifo_level) );

endmodule // simple_uart_rx
module simple_uart_tx
    #(parameter SIZE=0)
    (input clk, input rst,
     input [7:0] fifo_in, input fifo_write, output [15:0] fifo_level, output fifo_full, 
     input [15:0] clkdiv, output baudclk, output reg tx);

   reg [15:0] 	  baud_ctr;
   reg [3:0] 	  bit_ctr;

   wire 	  read, empty;
   wire [7:0] 	  char_to_send;
   wire 	  i_tready, o_tvalid;

   assign fifo_full = ~i_tready;
   assign empty = ~o_tvalid;

   axi_fifo #(.WIDTH(8), .SIZE(SIZE)) fifo
     (.clk(clk),.reset(rst), .clear(1'b0),
      .i_tdata(fifo_in), .i_tvalid(fifo_write), .i_tready(i_tready),
      .o_tdata(char_to_send),.o_tvalid(o_tvalid),.o_tready(read),
      .space(fifo_level),.occupied() );

   always @(posedge clk)
     if(rst)
       baud_ctr <= 0;
     else if (baud_ctr >= clkdiv)
       baud_ctr <= 1;
     else
       baud_ctr <= baud_ctr + 1;

   always @(posedge clk)
     if(rst)
       bit_ctr <= 0;
     else if(baud_ctr == clkdiv)
       if(bit_ctr == 10)
	 bit_ctr <= 0;
       else if(bit_ctr != 0)
	 bit_ctr <= bit_ctr + 1;
       else if(~empty)
	 bit_ctr <= 1;

   always @(posedge clk)
     if(rst)
       tx <= 1;
     else
       case(bit_ctr)
	 0 : tx <= 1;
	 1 : tx <= 0;
	 2 : tx <= char_to_send[0];
	 3 : tx <= char_to_send[1];
	 4 : tx <= char_to_send[2];
	 5 : tx <= char_to_send[3];
	 6 : tx <= char_to_send[4];
	 7 : tx <= char_to_send[5];
	 8 : tx <= char_to_send[6];
	 9 : tx <= char_to_send[7];
	 default : tx <= 1;
       endcase // case(bit_ctr)

   assign 	  read = (bit_ctr == 9) && (baud_ctr == clkdiv);
   assign 	  baudclk = (baud_ctr == 1);  // Only for debug purposes

endmodule // simple_uart_tx
module settings_bus
  #(parameter AWIDTH=16, parameter DWIDTH=32, parameter SWIDTH=8)
    (input wb_clk, 
     input wb_rst, 
     input [AWIDTH-1:0] wb_adr_i,
     input [DWIDTH-1:0] wb_dat_i,
     input wb_stb_i,
     input wb_we_i,
     output reg wb_ack_o,
     output reg strobe,
     output reg [SWIDTH-1:0] addr,
     output reg [31:0] data);

   reg 	    stb_int, stb_int_d1;
   
   always @(posedge wb_clk)
     if(wb_rst)
       begin
	  strobe <= 1'b0;
	  addr <= {SWIDTH{1'b0}};
	  data <= 32'd0;
       end
     else if(wb_we_i & wb_stb_i & ~wb_ack_o)
       begin
	  strobe <= 1'b1;
	  addr <= wb_adr_i[SWIDTH+1:2];
	  data <= wb_dat_i;
       end
     else
       strobe <= 1'b0;

   always @(posedge wb_clk)
     if(wb_rst)
       wb_ack_o <= 0;
     else
       wb_ack_o <= wb_stb_i & ~wb_ack_o;

endmodule // settings_bus
module simple_uart
  #(parameter CLKDIV_DEFAULT = 16'd0, parameter RX_SIZE=8, parameter TX_SIZE=0)
   (input clk_i, input rst_i,
    input we_i, input stb_i, input cyc_i, output reg ack_o,
    input [2:0] adr_i, input [31:0] dat_i, output reg [31:0] dat_o,
    output rx_int_o, output tx_int_o, output tx_o, input rx_i, output baud_o);

   // Register Map
   localparam SUART_CLKDIV = 0;
   localparam SUART_TXLEVEL = 1;
   localparam SUART_RXLEVEL = 2;
   localparam SUART_TXCHAR = 3;
   localparam SUART_RXCHAR = 4;

   wire       wb_acc = cyc_i & stb_i;            // WISHBONE access
   wire       wb_wr  = wb_acc & we_i;            // WISHBONE write access

   reg [15:0] clkdiv;
   wire [7:0] rx_char;
   wire       tx_fifo_full, rx_fifo_empty;
   wire [15:0] tx_fifo_level, rx_fifo_level;

   always @(posedge clk_i)
     if (rst_i)
       ack_o <= 1'b0;
     else
       ack_o <= wb_acc & ~ack_o;

   always @(posedge clk_i)
     if (rst_i)
       clkdiv <= CLKDIV_DEFAULT;
     else if (wb_wr)
       case(adr_i)
	 SUART_CLKDIV : clkdiv <= dat_i[15:0];
       endcase // case(adr_i)

   always @(posedge clk_i)
     case (adr_i)
       SUART_TXLEVEL : dat_o <= tx_fifo_level;
       SUART_RXLEVEL : dat_o <= rx_fifo_level;
       SUART_RXCHAR : dat_o <= rx_char;
     endcase // case(adr_i)

   simple_uart_tx #(.SIZE(TX_SIZE)) simple_uart_tx
     (.clk(clk_i),.rst(rst_i),
      .fifo_in(dat_i[7:0]),.fifo_write(ack_o && wb_wr && (adr_i == SUART_TXCHAR)),
      .fifo_level(tx_fifo_level),.fifo_full(tx_fifo_full),
      .clkdiv(clkdiv),.baudclk(baud_o),.tx(tx_o));

   simple_uart_rx #(.SIZE(RX_SIZE)) simple_uart_rx
     (.clk(clk_i),.rst(rst_i),
      .fifo_out(rx_char),.fifo_read(ack_o && ~wb_wr && (adr_i == SUART_RXCHAR)),
      .fifo_level(rx_fifo_level),.fifo_empty(rx_fifo_empty),
      .clkdiv(clkdiv),.rx(rx_i));

   assign     tx_int_o = ~tx_fifo_full;
   assign     rx_int_o = ~rx_fifo_empty;

endmodule // simple_uart
module simple_uart_tb();
   
   localparam SUART_CLKDIV = 0;
   localparam SUART_TXLEVEL = 1;
   localparam SUART_RXLEVEL = 2;
   localparam SUART_TXCHAR = 3;
   localparam SUART_RXCHAR = 4;
   
   reg           clk;
   reg 		 rst;

   reg 		 we_i;
   reg 		 stb_i;
   reg 		 cyc_i;
   wire 	 ack_o;
   reg [2:0] 	 adr_i;
   reg [31:0] 	 dat_i;
   wire [31:0] 	 dat_o;
   wire 	 rx_int_o;
   wire 	 tx_int_o;
   wire 	 tx_o;
   reg 		 rx_i;
   wire 	 baud_o;

   reg [31:0] 	 read_data;
   

   initial 
     clk = 0;

   // 200MHz clock
   always
     #2.5 clk = ~clk;

   initial begin
      rst <= 0;
      we_i <= 0;
      stb_i <= 0;
      cyc_i <= 0;
      adr_i <= 0;
      dat_i <= 0;
      rx_i <= 0;
   end
   
   
   task write_wb;
      input [31:0] data_in;
      input [2:0]  addr_in;

      begin
	 @(negedge clk);	 
	 dat_i <= data_in;
	 adr_i <= addr_in;
	 we_i <= 1;
	 stb_i <= 1;
	 cyc_i <= 1;
	 @(negedge clk);
	 while (ack_o == 0) begin
	    @(negedge clk);
	 end
	 dat_i <= 0;
	 adr_i <= 0;
	 we_i <= 0;
	 stb_i <= 0;
	 cyc_i <= 0;
      end
   endtask // write_wb

   
   task read_wb;
      output [31:0] data_out;
      input [2:0]  addr_in;

      begin
	 @(negedge clk);	 
	 adr_i <= addr_in;
	 we_i <= 0;
	 stb_i <= 1;
	 cyc_i <= 1;
	 @(negedge clk);
	 while (ack_o == 0) begin
	    @(negedge clk);
	 end
	 data_out <= dat_o;
	 adr_i <= 0;
	 stb_i <= 0;
	 cyc_i <= 0;
      end
   endtask // write_wb

   initial begin
      @(negedge clk);    
      rst <= 1;
      repeat(10) @(negedge clk);
      rst <= 0;
      repeat(10) @(negedge clk);
      write_wb(4'h0620,SUART_CLKDIV);
      repeat(10) @(negedge clk);
      read_wb(read_data,SUART_TXLEVEL);
      repeat(10) @(negedge clk);
   end // initial begin
   
   
   
   simple_uart
     #(.CLKDIV_DEFAULT(16'd0))
   simple_uart_i
     (
      .clk_i(clk),
      .rst_i(rst),
      .we_i(we_i),
      .stb_i(stb_i),
      .cyc_i(cyc_i),
      .ack_o(ack_o),
      .adr_i(adr_i),
      .dat_i(dat_i),
      .dat_o(dat_o),
      .rx_int_o(rx_int_o),
      .tx_int_o(tx_int_o), 
      .tx_o(tx_o), 
      .rx_i(rx_i),
      .baud_o(baud_o)
      );

   

endmodule // simple_uart_tb
module settings_readback
  #(parameter AWIDTH=16, parameter DWIDTH=32, parameter RB_ADDRW=2)
   (
    input wb_clk, 
    input wb_rst, 
    input [AWIDTH-1:0] wb_adr_i,
    input wb_stb_i,
    input wb_we_i,
    input [DWIDTH-1:0] rb_data,
    output reg [RB_ADDRW-1:0] rb_addr,
    output [DWIDTH-1:0] wb_dat_o,
    output reg rb_rd_stb
    );

   always @(posedge wb_clk)
     if (wb_stb_i && ~wb_we_i) begin
	rb_addr <= wb_adr_i[RB_ADDRW+1:2];
	rb_rd_stb <= 1'b1;	
     end else begin
	rb_rd_stb <= 1'b0;	
     end
   
   assign wb_dat_o = rb_data;

   

endmodule // settings_readback
module refill_randomizer
  #(parameter BITS=7)
    (
     input clk,
     input rst,
     input full_in,
     output full_out
     );
   
   wire 	    feedback;
   reg 	    full_last;
   wire     full_deasserts;
   reg [6:0] shift_reg;
   reg [6:0] count;
   reg 	     delayed_fall;
   

   always @(posedge clk)
     full_last <= full_in;
   
   assign    full_deasserts = full_last & ~full_in;

   // 7 bit LFSR
   always @(posedge clk)
     if (rst)
       shift_reg <= 7'b1;
     else
       if (full_deasserts)
	 shift_reg <= {shift_reg[5:0],feedback};

   assign    feedback = ^(shift_reg & 7'h41);

   always @(posedge clk)
     if (rst)
       begin
	  count <= 1;
	  delayed_fall  <= 1;
       end
     else if (full_deasserts)
       begin
	  count <= shift_reg;
	  delayed_fall <= 1;
       end
     else if (count == 1)
       begin
	  count <= 1;
	  delayed_fall <= 0;
       end
     else
       begin
	  count <= count - 1;
	  delayed_fall <= 1;
       end
   
   // Full_out goes instantly high if full_in does. However its fall is delayed.
   assign    full_out = (full_in == 1) || (full_last == 1) || delayed_fall;

endmodule
module nobl_if
  #(parameter WIDTH=18,DEPTH=19)  
    (
     input clk,
     input rst,
     input [WIDTH-1:0] RAM_D_pi,
     output [WIDTH-1:0] RAM_D_po,
     output reg RAM_D_poe,
     output [DEPTH-1:0] RAM_A,
     output reg RAM_WEn,
     output RAM_CENn,
     output RAM_LDn,
     output RAM_OEn,
     output reg RAM_CE1n,
     input [DEPTH-1:0] address,
     input [WIDTH-1:0] data_out,
     output reg [WIDTH-1:0] data_in,
     output reg data_in_valid,
     input write,
     input enable
     );
   

   reg 	   enable_pipe1;
   reg [DEPTH-1:0] address_pipe1;
   reg 		   write_pipe1;
   reg [WIDTH-1:0] data_out_pipe1;
   
   reg 		   enable_pipe2;
   reg 		   write_pipe2;
   reg [WIDTH-1:0] data_out_pipe2;

   reg 		   enable_pipe3;
   reg 		   write_pipe3;
   reg [WIDTH-1:0] data_out_pipe3;

   assign 	   RAM_LDn = 0;
   // ZBT/NoBL RAM actually manages its own output enables very well.
   assign 	   RAM_OEn = 0;

   // gray code the address to reduce EMI
   wire [DEPTH-1:0] address_gray;
   
   bin2gray #(.WIDTH(DEPTH)) bin2gray (.bin(address),.gray(address_gray));
   
   
   //
   // Pipeline stage 1
   //
   always @(posedge clk)
     if (rst)
       begin
	  enable_pipe1 <= 0;
	  address_pipe1 <= 0;
	  write_pipe1 <= 0;
	  data_out_pipe1  <= 0;
	  RAM_WEn <= 1;
	  RAM_CE1n <= 1;
	  
       end
     else
       begin
	  enable_pipe1 <= enable;
	  RAM_CE1n <= ~enable;  // Creates IOB flop
	  RAM_WEn <= ~write;  // Creates IOB flop
	  
	  if (enable)
	    begin
	       address_pipe1 <= address_gray;
	       write_pipe1 <= write;
//	       RAM_WEn <= ~write;  // Creates IOB flop
	       
	       
	       if (write)
		 data_out_pipe1 <= data_out;
	    end
       end // always @ (posedge clk)

   // Pipeline 1 drives address, write_enable, chip_select on NoBL SRAM
   assign RAM_A = address_pipe1;
   assign RAM_CENn = 1'b0;
 //  assign RAM_WEn = ~write_pipe1;
//   assign RAM_CE1n = ~enable_pipe1;

   //
   // Pipeline stage2
   //
   always @(posedge clk)
     if (rst)
       begin
	  enable_pipe2 <= 0;
	  data_out_pipe2 <= 0;
	  write_pipe2 <= 0;   
       end
     else
       begin
	  data_out_pipe2 <= data_out_pipe1;
	  write_pipe2 <= write_pipe1;
	  enable_pipe2 <= enable_pipe1;
       end
   
   //
   // Pipeline stage3
   //
   always @(posedge clk)
     if (rst)
       begin
	  enable_pipe3 <= 0;
	  data_out_pipe3 <= 0;
	  write_pipe3 <= 0;
	  RAM_D_poe <= 0;	  
       end
     else
       begin
	  data_out_pipe3 <= data_out_pipe2;
	  write_pipe3 <= write_pipe2;
	  enable_pipe3 <= enable_pipe2;
	  RAM_D_poe <= ~(write_pipe2 & enable_pipe2); // Active low driver enable in Xilinx.	
       end

   // Pipeline 3 drives write data on NoBL SRAM
   assign RAM_D_po = data_out_pipe3;
   
   
   //
   // Pipeline stage4
   //
   always @(posedge clk)
     if (rst)
       begin
	  data_in_valid <= 0;
	  data_in <= 0;
       end
     else
       begin
	  data_in <= RAM_D_pi;
	  if (enable_pipe3 & ~write_pipe3)
	    begin
	       // Read data now available to be registered.
	       data_in_valid <= 1'b1;
	    end
	  else
	    data_in_valid <= 1'b0;
       end // always @ (posedge clk)
     
endmodule // nobl_if
module nobl_fifo
  #(parameter WIDTH=18,RAM_DEPTH=19,FIFO_DEPTH=19)
    (   
	input clk,
	input rst,
	input [WIDTH-1:0] RAM_D_pi,
	output [WIDTH-1:0] RAM_D_po,
	output RAM_D_poe,
	output [RAM_DEPTH-1:0] RAM_A,
	output RAM_WEn,
	output RAM_CENn,
	output RAM_LDn,
	output RAM_OEn,
	output RAM_CE1n,
	input [WIDTH-1:0] write_data,
	input write_strobe,
	output reg space_avail,
	output  [WIDTH-1:0] read_data,
	input read_strobe,                    // Triggers a read, result in approximately 6 cycles.
	output  data_avail,                    // Qulaifys read data available this cycle on read_data.
	output reg [FIFO_DEPTH-1:0] capacity
	);

   //reg [FIFO_DEPTH-1:0] capacity;
   reg [FIFO_DEPTH-1:0] wr_pointer;
   reg [FIFO_DEPTH-1:0] rd_pointer;
   wire [RAM_DEPTH-1:0] address;
   reg 			data_avail_int;  // Internal not empty flag.
   
   assign 	    read = read_strobe && data_avail_int;
   assign 	    write = write_strobe && space_avail;

   // When a read and write collision occur, supress the space_avail flag next cycle
   // and complete write followed by read over 2 cycles. This forces balanced arbitration
   // and makes for a simple logic design.

   always @(posedge clk)
     if (rst)
       begin
	  capacity <= (1 << FIFO_DEPTH) - 1;
	  wr_pointer <= 0;
	  rd_pointer <= 0;
	  space_avail <= 1;
	  data_avail_int <= 0;
       end
     else	  
       begin
	  // No space available if:
	  // Capacity is already zero; Capacity is 1 and write is asserted (lookahead); both read and write are asserted (collision)
	  space_avail <= ~((capacity == 0) || (read&&write) || ((capacity == 1) && write) );
	  // Capacity has 1 cycle delay so look ahead here for corner case of read of last item in FIFO.
	  data_avail_int <= ~((capacity == ((1 << FIFO_DEPTH)-1))  || ((capacity == ((1 << FIFO_DEPTH)-2)) && (~write && read))  );
	  wr_pointer <= wr_pointer + write;
	  rd_pointer <= rd_pointer + (~write && read); 
	  capacity <= capacity - write + (~write && read) ;
       end // else: !if(rst)

   assign address = write ? wr_pointer : rd_pointer;
   assign enable = write || read; 


   //
   // Simple NoBL SRAM interface, 4 cycle read latency.
   // Read/Write arbitration via temprary application of empty/full flags.
   //
   nobl_if #(.WIDTH(WIDTH),.DEPTH(RAM_DEPTH))
     nobl_if_i1
       (
	.clk(clk),
	.rst(rst),
	.RAM_D_pi(RAM_D_pi),
	.RAM_D_po(RAM_D_po),
	.RAM_D_poe(RAM_D_poe),
	.RAM_A(RAM_A),
	.RAM_WEn(RAM_WEn),
	.RAM_CENn(RAM_CENn),
	.RAM_LDn(RAM_LDn),
	.RAM_OEn(RAM_OEn),
	.RAM_CE1n(RAM_CE1n),
	.address(address),
	.data_out(write_data),
	.data_in(read_data),
	.data_in_valid(data_avail),
	.write(write),
	.enable(enable)
	);

   

endmodule // nobl_fifo
module cvita_chunker # (
   parameter PAD_VALUE = 64'hFFFFFFFF_FFFFFFFF,
             HOLD_ERROR = 1'b1 // If high, hold error until reset, else pulse
) (
   input wire          clk,
   input wire          reset,
   input wire          clear,
   input wire [15:0]   frame_size,

   input wire [63:0]   i_tdata,
   input wire          i_tlast,
   input wire          i_tvalid,
   output reg          i_tready,
   
   output wire [63:0]  o_tdata,
   output wire         o_tlast,
   output reg          o_tvalid,
   input  wire         o_tready,
   
   output wire         error
);

   localparam ST_HEADER  = 2'd0;
   localparam ST_DATA    = 2'd1;
   localparam ST_PADDING = 2'd2;
   localparam ST_ERROR   = 2'd3;

   reg [1:0]   state;
   reg [15:0]  frame_rem;

   wire [15:0] cvita_len_ceil = i_tdata[47:32] + 16'd7;
   wire [15:0] axi_len = {3'b000, cvita_len_ceil[15:3]};

   always @(posedge clk) begin
      if (reset | clear) begin
         state <= ST_HEADER;
         frame_rem <= 16'd0;
      end else if ((state == ST_ERROR) & i_tlast & i_tvalid & !HOLD_ERROR) begin
         state <= ST_HEADER;
         frame_rem <= 16'd0;
      end else if (o_tready) begin
         case (state)
            ST_HEADER: begin
               if (i_tvalid) begin
                  if ((axi_len > frame_size) | (axi_len == 16'd0))
                     state <= ST_ERROR;
                  else if (i_tlast)
                     state <= ST_PADDING;
                  else
                     state <= ST_DATA;
                     
                  frame_rem <= frame_size - 16'd1;
               end
            end

            ST_DATA: begin
               if (i_tvalid) begin
                  if (i_tlast) begin
                     state   <= o_tlast ? ST_HEADER : ST_PADDING;
                     frame_rem <= o_tlast ? 16'd0 : (frame_rem - 16'd1);
                  end else begin
                     state <= ST_DATA;
                     frame_rem <= frame_rem - 16'd1;
                  end
               end
            end

            ST_PADDING: begin
               if (o_tlast) begin
                  state   <= ST_HEADER;
                  frame_rem <= 16'd0;
               end else begin
                  state   <= ST_PADDING;
                  frame_rem <= frame_rem - 16'd1;
               end
            end

         endcase
      end
   end

   always @(*) begin
      case (state)
         ST_HEADER: begin
            i_tready = o_tready;
            o_tvalid = (axi_len <= frame_size) & (axi_len > 16'd0) & i_tvalid;
         end

         ST_DATA: begin
            i_tready = o_tready;
            o_tvalid = i_tvalid;
         end

         ST_PADDING: begin
            i_tready = 1'b0;
            o_tvalid = 1'b1;
         end

         ST_ERROR: begin
            i_tready = 1'b1;
            o_tvalid = 1'b0;
         end

         default: begin
            i_tready = 1'b0;
            o_tvalid = 1'b0;
         end
      endcase
   end

   assign o_tlast = (frame_rem != 16'd0) ? (frame_rem == 16'd1) : (axi_len == 16'd1);
   assign o_tdata = (state == ST_PADDING) ? PAD_VALUE : i_tdata;

   assign error = (state == ST_ERROR);

endmodule // cvita_chunker
module ip_hdr_checksum
  (input clk, input [159:0] in, output reg [15:0] out);

   wire [18:0] padded [0:9];
   reg [18:0]  sum_a, sum_b;
   
   genvar     i;
   generate
      for(i=0 ; i<10 ; i=i+1)
	assign padded[i] = {3'b000,in[i*16+15:i*16]};
   endgenerate

   always @(posedge clk)  sum_a = padded[0] + padded[1] + padded[2] + padded[3] + padded[4];
   always @(posedge clk)  sum_b = padded[5] + padded[6] + padded[7] + padded[8] + padded[9];

   wire [18:0] sum = sum_a + sum_b;

   always @(posedge clk)
     out <= ~(sum[15:0] + {13'd0,sum[18:16]});
   
   
endmodule // ip_hdr_checksum