dakies/OSS_Verilog huggingface dataset:
module sine_tone #(
  parameter WIDTH = 32,
  parameter SR_PHASE_INC_ADDR = 129,
  parameter SR_CARTESIAN_ADDR = 130)
(
  input clk, input reset, input clear, input enable,
  input set_stb, input [WIDTH-1:0] set_data, input [7:0] set_addr,
  output [WIDTH-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready
);

  wire [15:0] phase_in_tdata;
  wire phase_in_tlast;
  wire phase_in_tvalid ;
  wire phase_in_tready;

  wire [15:0] phase_out_tdata;
  wire phase_out_tlast;
  wire phase_out_tvalid;
  wire phase_out_tready;

  wire [WIDTH-1:0] cartesian_tdata;
  wire cartesian_tlast;
  wire cartesian_tvalid;
  wire cartesian_tready;

  wire [WIDTH-1:0] sine_out_tdata;
  wire sine_out_tlast;
  wire sine_out_tvalid;
  wire sine_out_tready;

//AXI settings bus for phase values
  axi_setting_reg #(
    .ADDR(SR_PHASE_INC_ADDR), .AWIDTH(8), .WIDTH(16), .STROBE_LAST(1), .REPEATS(1))
  set_phase_acc (
    .clk(clk), .reset(reset),
    .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
    .o_tdata(phase_in_tdata), .o_tlast(phase_in_tlast), .o_tvalid(phase_in_tvalid), .o_tready(phase_in_tready & enable));

//AXI settings bus for cartestian values
  axi_setting_reg #(
    .ADDR(SR_CARTESIAN_ADDR), .AWIDTH(8), .WIDTH(32), .REPEATS(1))
  set_axis_cartesian (
    .clk(clk), .reset(reset),
    .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
    .o_tdata(cartesian_tdata), .o_tlast(), .o_tvalid(cartesian_tvalid), .o_tready(cartesian_tready & enable));

  assign cartesian_tlast = 1;

//Phase Accumulator
  phase_accum phase_acc (
    .clk(clk), .reset(reset), .clear(clear),
    .i_tdata(phase_in_tdata), .i_tlast(phase_in_tlast), .i_tvalid(1'b1), .i_tready(phase_in_tready),
    .o_tdata(phase_out_tdata), .o_tlast(phase_out_tlast), .o_tvalid(phase_out_tvalid), .o_tready(phase_out_tready & enable));

//Cordic
   cordic_rotator cordic_inst (
    .aclk(clk), .aresetn(~(reset|clear)),
    .s_axis_phase_tdata(phase_out_tdata),
    .s_axis_phase_tvalid(phase_out_tvalid & cartesian_tvalid & enable),
    .s_axis_phase_tready(phase_out_tready),
    .s_axis_cartesian_tdata(cartesian_tdata),
    .s_axis_cartesian_tlast(cartesian_tlast),
    .s_axis_cartesian_tvalid(phase_out_tvalid & cartesian_tvalid & enable),
    .s_axis_cartesian_tready(cartesian_tready),
    .m_axis_dout_tdata(sine_out_tdata),
    .m_axis_dout_tlast(sine_out_tlast),
    .m_axis_dout_tvalid(sine_out_tvalid),
    .m_axis_dout_tready(sine_out_tready & enable));

  assign o_tdata = sine_out_tdata;
  assign o_tlast = sine_out_tlast;
  assign o_tvalid = sine_out_tvalid;
  assign sine_out_tready = o_tready;

endmodule  //sine_tone
module cvita_hdr_encoder (
  input [1:0] pkt_type, input eob, input has_time,
  input [11:0] seqnum,
  input [15:0] payload_length,
  input [15:0] src_sid, input [15:0] dst_sid,
  input [63:0] vita_time,
  output [127:0] header
);

  assign header = {pkt_type, has_time, eob, seqnum,
                   payload_length + (has_time ? 16'd16 : 16'd8),
                   src_sid, dst_sid, vita_time};

endmodule
module axi_pipe
  #(parameter STAGES=3)
   (input clk, input reset, input clear,
    input i_tlast, input i_tvalid, output i_tready,
    output o_tlast, output o_tvalid, input o_tready,
    output [STAGES-1:0] enables,
    output reg [STAGES-1:0] valids);

   assign o_tvalid = valids[STAGES-1];
   assign i_tready = enables[0];

   // //////////////////////////////
   // Valids
   genvar 		    i;
   generate
      for(i=1; i<STAGES; i=i+1)
	always @(posedge clk)
	  if(reset | clear)
	    valids[i] <= 1'b0;
      	  else
	    valids[i] <= valids[i-1] | (valids[i] & ~enables[i]);
   endgenerate

   always @(posedge clk)
     if(reset | clear)
       valids[0] <= 1'b0;
     else
       valids[0] <= i_tvalid | (valids[0] & ~enables[0]);

   // //////////////////////////////
   // Enables
   genvar 		    j;
   generate
      for(j=0; j<STAGES; j=j+1)
	assign enables[j] = o_tready | (|(~valids[STAGES-1:j]));
   endgenerate

   // /////////////////////////////
   // tlast
   reg [STAGES-1:0] 	    tlast;
   
   genvar 		    k;
   generate
      for(k=1; k<STAGES; k=k+1)
	always @(posedge clk)
	  if(reset | clear)
	    tlast[k] <= 1'b0;
	  else if(enables[k])
	    tlast[k] <= tlast[k-1];
   endgenerate

   always @(posedge clk)
	  if(reset | clear)
	    tlast[0] <= 1'b0;
	  else if(enables[0])
	    tlast[0] <= i_tlast;

   assign o_tlast = tlast[STAGES-1];
   
endmodule // axi_pipe
module threshold_scaled
  #(parameter WIDTH=32, SCALAR=131072)
   (input clk, input reset, input clear,
    input [WIDTH-1:0] i0_tdata, input i0_tlast, input i0_tvalid, output i0_tready,
    input [WIDTH-1:0] i1_tdata, input i1_tlast, input i1_tvalid, output i1_tready,
    output o_tdata, output o_tlast, output o_tvalid, input o_tready);

   wire signed [WIDTH-1:0] scaled_input;
   wire signed [WIDTH-1:0] difference;
   wire signed 		   thresh_met;
   
   assign scaled_input = (i1_tdata-1) * SCALAR;
   assign difference = scaled_input - i0_tdata;
   assign thresh_met = difference > 0;
   
   assign o_tdata = thresh_met;
   assign o_tlast = i0_tlast;

   wire 		   do_op = o_tready & i0_tvalid & i1_tvalid;
   
   assign o_tvalid = do_op;
   
   assign i0_tready = do_op;
   assign i1_tready = do_op;

endmodule // threshold_scaled
module complex_to_magsq #(
  parameter WIDTH = 16)
(
  input clk, input reset, input clear,
  input [2*WIDTH-1:0] i_tdata, input i_tlast, input i_tvalid, output i_tready,
  output [2*WIDTH-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready);

   wire [WIDTH-1:0]    ii_tdata, iq_tdata;
   wire 	       ii_tlast, ii_tvalid, ii_tready, iq_tlast, iq_tvalid, iq_tready;

   wire [2*WIDTH-1:0]    i_sq_tdata;
   wire 	       i_sq_tlast, i_sq_tvalid, i_sq_tready;

   split_complex #(.WIDTH(WIDTH)) split_complex
     (.i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
      .oi_tdata(ii_tdata), .oi_tlast(ii_tlast), .oi_tvalid(ii_tvalid), .oi_tready(ii_tready), 
      .oq_tdata(iq_tdata), .oq_tlast(iq_tlast), .oq_tvalid(iq_tvalid), .oq_tready(iq_tready),
      .error());
      
  // i^2
  mult #(
   .WIDTH_A(WIDTH),
   .WIDTH_B(WIDTH),
   .WIDTH_P(2*WIDTH),
   .DROP_TOP_P(5),
   .LATENCY(2),       // NOTE: If using CASCADE_OUT, set to 3
   .CASCADE_OUT(0))   // FIXME can use cascade once we get ISE to accept it
  i_sq_mult (
    .clk(clk), .reset(reset),
    .a_tdata(ii_tdata), .a_tlast(ii_tlast), .a_tvalid(ii_tvalid), .a_tready(ii_tready),
    .b_tdata(ii_tdata), .b_tlast(ii_tlast), .b_tvalid(ii_tvalid), .b_tready(),
    .p_tdata(i_sq_tdata), .p_tlast(i_sq_tlast), .p_tvalid(i_sq_tvalid), .p_tready(i_sq_tready));

  // q^2 + i^2
  mult_add #(
   .WIDTH_A(WIDTH),
   .WIDTH_B(WIDTH),
   .WIDTH_P(2*WIDTH),
   .DROP_TOP_P(5),
   .LATENCY(4),
   .CASCADE_IN(0),   // FIXME this can be 1 once we get ISE to accept cascading
   .CASCADE_OUT(0))
  q_sq_mult (
    .clk(clk), .reset(reset),
    .a_tdata(iq_tdata), .a_tlast(iq_tlast), .a_tvalid(iq_tvalid), .a_tready(iq_tready),
    .b_tdata(iq_tdata), .b_tlast(iq_tlast), .b_tvalid(iq_tvalid), .b_tready(),
    .c_tdata(i_sq_tdata), .c_tlast(i_sq_tlast), .c_tvalid(i_sq_tvalid), .c_tready(i_sq_tready),
    .p_tdata(o_tdata), .p_tlast(o_tlast), .p_tvalid(o_tvalid), .p_tready(o_tready));

endmodule
module cvita_hdr_modify (
  input  [127:0] header_in,
  output [127:0] header_out,
  input use_pkt_type,       input [1:0] pkt_type,
  input use_has_time,       input has_time,
  input use_eob,            input eob,
  input use_seqnum,         input [11:0] seqnum,
  input use_length,         input [15:0] length,
  input use_payload_length, input [15:0] payload_length,
  input use_src_sid,        input [15:0] src_sid,
  input use_dst_sid,        input [15:0] dst_sid,
  input use_vita_time,      input [63:0] vita_time
);

  wire [15:0] length_adj = payload_length + (header_out[125] /* Has time */ ? 16'd16 : 16'd8);

  assign header_out = {
    (use_pkt_type       == 1'b1) ? pkt_type   : header_in[127:126],
    (use_has_time       == 1'b1) ? has_time   : header_in[125],
    (use_eob            == 1'b1) ? eob        : header_in[124],
    (use_seqnum         == 1'b1) ? seqnum     : header_in[123:112],
    (use_length         == 1'b1) ? length     :
    (use_payload_length == 1'b1) ? length_adj : header_in[111:96],
    (use_src_sid        == 1'b1) ? src_sid    : header_in[95:80],
    (use_dst_sid        == 1'b1) ? dst_sid    : header_in[79:64],
    (use_vita_time      == 1'b1) ? vita_time  : header_in[63:0]};

endmodule
module fir_filter_slice #(
  parameter IN_WIDTH     = 16,
  parameter COEFF_WIDTH  = 16,
  parameter ACCUM_WIDTH  = 32,
  parameter OUT_WIDTH    = 32)
(
  input clk,
  input reset,
  input clear,
  input sample_in_stb,
  input signed [IN_WIDTH-1:0] sample_in_a,       // Sample in
  input signed [IN_WIDTH-1:0] sample_in_b,       // Sample in for symmetric filters
  output signed [IN_WIDTH-1:0] sample_forward,   // Delayed sample in to forward
  input signed [COEFF_WIDTH-1:0] coeff_in,       // Filter tap coefficient
  output signed [COEFF_WIDTH-1:0] coeff_forward, // Filter tap coefficient to forward
  input coeff_load_stb,                          // Load coefficient
  input signed [ACCUM_WIDTH-1:0] sample_accum,   // Accumulating path
  output signed [OUT_WIDTH-1:0] sample_out       // Result
);

  reg signed [IN_WIDTH-1:0] a_reg[0:1];
  reg signed [IN_WIDTH-1:0] d_reg;
  reg signed [IN_WIDTH:0] ad_reg;
  reg signed [COEFF_WIDTH-1:0] b_reg[0:1];
  reg signed [IN_WIDTH+COEFF_WIDTH:0] m_reg;
  reg signed [ACCUM_WIDTH-1:0] p_reg;

  always @(posedge clk) begin
    if (reset | clear) begin
      a_reg[0]   <= 0;
      a_reg[1]   <= 0;
      d_reg      <= 0;
      b_reg[0]   <= 0;
      b_reg[1]   <= 0;
      ad_reg     <= 0;
      m_reg      <= 0;
      p_reg      <= 0;
    end else begin
      if (sample_in_stb) begin
        a_reg[0] <= sample_in_a;
        a_reg[1] <= a_reg[0];
        d_reg    <= sample_in_b;
        ad_reg   <= a_reg[1] + d_reg;
        m_reg    <= ad_reg * b_reg[1];
        p_reg    <= sample_accum + m_reg;
      end
      if (coeff_load_stb) begin
        b_reg[0] <= coeff_in;
      end
      b_reg[1]   <= b_reg[0];
    end
  end

  assign coeff_forward  = b_reg[0];
  assign sample_forward = a_reg[1];
  assign sample_out     = p_reg[OUT_WIDTH-1:0];

endmodule
module packet_resizer
  #(parameter SR_PKT_SIZE=1)
   (input clk, input reset,
    input [15:0] next_dst_sid,
    input set_stb, input [7:0] set_addr, input [31:0] set_data,
    input [31:0] i_tdata, input [127:0] i_tuser, input i_tlast, input i_tvalid, output i_tready,
    output [31:0] o_tdata, output [127:0] o_tuser, output o_tlast, output o_tvalid, input o_tready);

   wire [15:0] 	  pkt_size;
   reg [15:0] 	  count;
   reg 		  first_packet_in_burst = 1'b1;
   
   setting_reg #(.my_addr(SR_PKT_SIZE), .width(16)) reg_pkt_size
     (.clk(clk), .rst(reset), .strobe(set_stb), .addr(set_addr), .in(set_data),
      .out(pkt_size));

   // Parse i_tuser
   wire [1:0] 	  TYPE_in = i_tuser[127:126];
   wire 	  TSI_in = i_tuser[125];
   wire 	  EOB_in = i_tuser[124];
   wire [11:0] 	  SEQ_in = i_tuser[123:112];
   wire [15:0] 	  LEN_in = i_tuser[111:96];
   wire [15:0] 	  SRC_in = i_tuser[95:80];
   wire [15:0] 	  DST_in = i_tuser[79:64];
   wire [63:0] 	  TIME_in = i_tuser[63:0];
   
   // Generate o_tuser
   wire [1:0] 	  TYPE_out = TYPE_in;
   wire 	  TSI_out = TSI_in & first_packet_in_burst;
   wire 	  EOB_out = EOB_in & i_tlast;
   wire [11:0] 	  SEQ_out = SEQ_in;     // Doesn't actually matter, it gets overwritten by chdr_framer
   wire [15:0] 	  LEN_out = LEN_in;     // Only the bottom 2 bits actually matter, rest gets overwritten
   wire [15:0] 	  SRC_out = DST_in;
   wire [15:0] 	  DST_out = next_dst_sid;
   wire [63:0] 	  TIME_out = TIME_in;

   // Pass nearly everything through unchanged
   assign o_tdata = i_tdata;
   assign o_tlast = (count == pkt_size) | EOB_out;   
   assign o_tuser = { TYPE_out, TSI_out, EOB_out, SEQ_out, LEN_out, SRC_out, DST_out, TIME_out };

   assign o_tvalid = i_tvalid;
   assign i_tready = o_tready;

   always @(posedge clk)
     if(reset)
       count <= 16'd4;
     else
       if(o_tvalid & o_tready)
	 if(o_tlast)
	   count <= 16'd4;
	 else
	   count <= count + 16'd4;

   always @(posedge clk)
     if(reset)
       first_packet_in_burst <= 1'b1;
     else
       if(o_tvalid & o_tready & o_tlast)
	 first_packet_in_burst <= EOB_out;
   
endmodule // packet_resizer
module cadd
  #(parameter WIDTH=16)
   (input clk, input reset,
    input [WIDTH*2-1:0] a_tdata, input a_tlast, input a_tvalid, output a_tready,
    input [WIDTH*2-1:0] b_tdata, input b_tlast, input b_tvalid, output b_tready,
    output [WIDTH*2-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready);

   wire int_tlast = a_tlast | b_tlast;
   wire int_tvalid, int_tready;
   wire [WIDTH*2-1:0] int_tdata;

   assign int_tdata[WIDTH*2-1:WIDTH] = a_tdata[WIDTH*2-1:WIDTH] + b_tdata[WIDTH*2-1:WIDTH];
   assign int_tdata[WIDTH-1:0] = a_tdata[WIDTH-1:0] + b_tdata[WIDTH-1:0];

   assign int_tvalid = a_tvalid & b_tvalid;
   assign a_tready = int_tvalid & int_tready;
   assign b_tready = a_tready;
   
   axi_fifo #(.WIDTH(WIDTH*2+1), .SIZE(0)) flop_output
     (.clk(clk), .reset(reset), .clear(1'b0),
      .i_tdata({int_tlast, int_tdata}), .i_tvalid(int_tvalid), .i_tready(int_tready),
      .o_tdata({o_tlast, o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready));
   
endmodule // cadd
module s7_icap_wb
  (
   input clk, 
   input reset,
   input cyc_i, 
   input stb_i, 
   input we_i, 
   output ack_o,
   input [31:0] dat_i, 
   output [31:0] dat_o
   );

   reg 		 rdwrb, csib;
   

   reg [2:0]    icap_state;
   localparam ICAP_IDLE  = 0;
   localparam ICAP_WR0   = 1;
   localparam ICAP_WR1   = 2;
   localparam ICAP_RD0   = 3;
   localparam ICAP_RD1   = 4;

   localparam IDLE = 1'b1;
   localparam ACTIVE = 1'b0;
   localparam READ = 1'b1;
   localparam WRITE = 1'b0;
   

   always @(posedge clk)
     if(reset) begin
	rdwrb <= READ;
	csib <= IDLE;
       icap_state <= ICAP_IDLE;
     end
     else
       case(icap_state)
	 //
	 // In IDLE state waiting for a READ or WRITE to be signalled from the WB bus.
	 // (In this state rdwrb can flip state without effect because ICAP is not selected)
	 //
         ICAP_IDLE :
           begin
              if(stb_i & cyc_i) begin
                 if(we_i) begin
		    // Start WRITE, assert RDWR_B LOW whilst CSI_B remains HIGH.
		    rdwrb <= WRITE;
		    csib <= IDLE;
		    icap_state <= ICAP_WR0;
		 end else begin
		    // Start READ
		    rdwrb <= READ;
		    csib <= IDLE;
		    icap_state <= ICAP_RD0;
		 end
	      end else begin
		 // Stay IDLE
		 rdwrb <= READ;
		 csib <= IDLE;
		 icap_state <= ICAP_IDLE;
	      end
	   end // case: ICAP_IDLE
	 //
	 // First cycle of WRITE.  
	 // Next cycle assert RDWR_B LOW and assert CSI_B LOW. 
	 //
         ICAP_WR0 : begin
	    rdwrb <= WRITE;
	    csib <= ACTIVE;
            icap_state <= ICAP_WR1;
	 end
	 //
	 // Second cycle of WRITE.
	 // Next cycle assert RDWR_B LOW and assert CSI_B HIGH whilst transitioning to IDLE state
	 //
         ICAP_WR1 : begin
	    rdwrb <= WRITE;
	    csib <= IDLE;
            icap_state <= ICAP_IDLE;
	 end
	 //
	 // First cycle of READ.
	 // Next cycle assert RDWR_B HIGH and assert CSI_B LOW. 
	 //
         ICAP_RD0 : begin
            rdwrb <= READ;
	    csib <= ACTIVE;
            icap_state <= ICAP_WR1;
	 end
	 //
	 // Second cycle of READ.
	 // Next cycle assert RDWR_B HIGH and assert CSI_B HIGH whilst transitioning to IDLE state
	 //
         ICAP_RD1 : begin
	    rdwrb <= READ;
	    csib <= IDLE;
            icap_state <= ICAP_IDLE;
	 end
        
       endcase // case (icap_state)

   assign ack_o = (icap_state == ICAP_WR1) | (icap_state == ICAP_RD1);
   //assign debug_out = {17'd0, BUSY, dat_i[7:0], ~CE, ICAPCLK, ~WRITE, icap_state};
 

   ICAPE2  #(
	     .DEVICE_ID(32'h03651093),
	     .ICAP_WIDTH("X32"),
	     .SIM_CFG_FILE_NAME("NONE")
	     )
     ICAPE2_inst  (
		   .O(/*dat_o[31:0]*/),
		   .CLK(clk),     // Rising edge referenced for both reads and writes.
		   .CSIB(csib),        // CSIB = 0 to select ICAP
		   .I(dat_i[31:0]),   // Bitswaped as per SELECTMAP (See UG470 page 40)
		   .RDWRB(rdwrb)     // RDWB = 0 for WRITE, = 1 for READ
		   );
   
   assign dat_0 = 32'h0;
   
endmodule // s3a_icap_wb
module serial_to_settings
  (
   input clk,
   input reset,
   // Serial signals (async)
   input scl,
   input sda,
   // Settngs bus out
   output reg set_stb,
   output reg [7:0] set_addr,
   output reg [31:0] set_data,
   // Debug
   output [31:0] debug
   );

   reg [2:0] 	 state;
   
   localparam 	 SEARCH = 3'h0;
   localparam 	 ADDRESS = 3'h1;
   localparam 	 DATA = 3'h2;
   localparam 	 STOP1 = 3'h3;
   localparam 	 STOP2 = 3'h4;
 	 
   reg 		 scl_pre_reg, scl_reg, scl_reg2;
   reg 		 sda_pre_reg, sda_reg, sda_reg2;
   reg [4:0] 	 counter;

 
     always @(posedge clk) begin
      scl_reg2 <= scl_reg;
      scl_reg <= scl_pre_reg;
      scl_pre_reg <= scl;
      sda_reg2 <= sda_reg;
      sda_reg <= sda_pre_reg;
      sda_pre_reg <= sda;
   end

   
   always @(posedge clk)
     if (reset) begin
	state <= SEARCH;
	counter <= 0;
	set_addr <= 0;
	set_data <= 0;
	set_stb <= 0;
     end else begin
	case(state)
	  //
	  // Search for I2C like start indication: SDA goes low whilst clock is high.
	  //
	  SEARCH: begin
	     set_stb <= 0;
	     // Look for START.
	     if (scl_reg && scl_reg2 && !sda_reg && sda_reg2) begin
		state <= ADDRESS;
		counter <= 0;
	     end
	  end
	  //
	  // Count 8 Address bits.
	  // Master changes SDA on falling edge of SCL, we sample on the rising edge.
	  //
	  ADDRESS: begin
	     if (scl_reg && !scl_reg2) begin
		set_addr[7:0] <= {set_addr[6:0],sda_reg};
		if (counter == 7) begin
		   state <= DATA;
		   counter <= 0;
		end else
		  counter <= counter + 1;		  
	    end
	  end
	  //
	  // Count 32 data bits.
	  // Master changes SDA on falling edge of SCL, we sample on the rising edge.
	  //
	  DATA: begin
	     if (scl_reg && !scl_reg2) begin
		set_data[31:0] <= {set_data[30:0],sda_reg};
		if (counter == 31) begin
		   state <= STOP1;
		   counter <= 0;
		end else
		  counter <= counter + 1;		  
	    end
	  end
	  //
	  // Looks for rising SCL edge before STOP bit.
	  //
	  STOP1: begin
	     if (scl_reg && !scl_reg2) begin
		state <= STOP2;
	     end
	  end
	  //
	  // Looks for STOP bit
	  //
	  STOP2: begin
	     if (scl_reg && scl_reg2 && sda_reg && !sda_reg2) begin
		state <= SEARCH;
		counter <= 0;
		set_stb <= 1;
	     end
	  end
	  
	endcase // case(state)
     end // else: !if(reset)

   assign debug =
		 {
		  counter[4:0],
		  state[2:0],
		  scl_reg,
		  sda_reg
		  };
   


endmodule // serial_to_settings
module regport_resp_mux #(
  parameter WIDTH      = 32,
  parameter NUM_SLAVES = 2
)(
  input                            clk,
  input                            reset,

  input [NUM_SLAVES-1:0]           sla_rd_resp,
  input [(NUM_SLAVES*WIDTH)-1:0]   sla_rd_data,

  output reg                       mst_rd_resp,
  output reg [WIDTH-1:0]           mst_rd_data
);
  // Treat sla_rd_resp as a one-hot bus.
  // If multiple resp lines are asserted at the same time, then
  // it is a violation of the register port protocol

  wire [NUM_SLAVES-1:0] bit_options[0:WIDTH-1];
  wire [WIDTH-1:0]      data_out;

  genvar i, b;
  generate
     for (b = 0; b < WIDTH; b = b + 1) begin
        for (i = 0; i < NUM_SLAVES; i = i + 1) begin
           assign bit_options[b][i] = sla_rd_data[(i*WIDTH)+b];
        end
        assign data_out[b] = |(bit_options[b] & sla_rd_resp);
     end
  endgenerate

  always @(posedge clk) begin
     mst_rd_data <= data_out;
     if (reset)
        mst_rd_resp <= 1'b0;
     else
        mst_rd_resp <= |(sla_rd_resp);
  end

endmodule
module radio_ctrl_proc_tb();

   reg clk    = 0;
   reg reset  = 1;

   always #10 clk = ~clk;

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

   initial
     begin
	#1000 reset = 0;
	#20000;
	$finish;
     end
   
   reg [63:0] vita_time = 64'd0;
   always @(posedge clk)
     if(reset) vita_time <= 64'd0;
     else vita_time <= vita_time + 64'd1;

   reg [63:0]  tdata;
   wire [63:0] tdata_int;
   reg 	       tlast;
   wire        tlast_int;
   reg 	       tvalid = 1'b0;
   wire        tvalid_int;
   wire        tready, tready_int;
   
   wire [7:0]  set_addr;
   wire [31:0] set_data;
   wire        set_stb;
   wire        ready = 1'b1;

   task send_packet;
      input ec;
      input timed;
      input [11:0] seqnum;
      input [31:0] sid;
      input [63:0] vtime;
      input [15:0] addr;
      input [31:0] data;
      
      begin
	 // Send a packet
	 @(posedge clk);
	 tlast <= 1'b0;
	 tdata <= { ec, 1'b0, timed, 1'b0, seqnum, timed ? 16'd6 : 16'd4, sid };
	 tvalid <= 1;
	 @(posedge clk);
	 if(timed)
	   begin
	      tdata <= vtime;
	      @(posedge clk);
	   end
	 tlast <= 1'b1;
	 tdata <= { 16'h0, addr, data };
	 @(posedge clk);
	 tvalid <= 0;	 
	 @(posedge clk);
      end
   endtask // send_packet
   
   initial
     begin
	tvalid <= 1'b0;
	while(reset)
	  @(posedge clk);
	send_packet(1'b1,1'b0,12'h5,32'hDEAD_BEEF,64'h0,16'hB,32'hF00D_1234);
	send_packet(1'b1,1'b1,12'h6,32'hDEAD_6789,64'h20,16'hC,32'hABCD_4321);
	send_packet(1'b1,1'b1,12'h7,32'hDEAD_6789,64'h30,16'hC,32'hABCD_4321);
	//send_packet(.ec(1), .timed(0), .seqnum(5), .sid(32'hDEAD_BEEF), .vtime(0), .addr(16'hB), .data(32'hF00D_1234));
     end

   axi_fifo_short #(.WIDTH(65)) axi_fifo_short
     (.clk(clk), .reset(reset), .clear(1'b0),
      .i_tdata({tlast,tdata}), .i_tvalid(tvalid), .i_tready(tready),
      .o_tdata({tlast_int,tdata_int}), .o_tvalid(tvalid_int), .o_tready(tready_int));

   wire [63:0] resp_tdata;
   wire        resp_tlast, resp_tvalid, resp_tready;
   
   radio_ctrl_proc radio_ctrl_proc
     (.clk(clk), .reset(reset), .clear(1'b0),
      .ctrl_tdata(tdata_int), .ctrl_tlast(tlast_int), .ctrl_tvalid(tvalid_int), .ctrl_tready(tready_int),
      .resp_tdata(resp_tdata), .resp_tlast(resp_tlast), .resp_tvalid(resp_tvalid), .resp_tready(resp_tready),
      .vita_time(vita_time), .ready(ready),
      .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
      .debug()
      );

   assign resp_tready = 1'b1;
   
   always @(posedge clk)
     if(resp_tvalid & resp_tready)
       begin
	  $display("%x",resp_tdata);
	  if(resp_tlast)
	    $display("TLAST");
       end
endmodule // radio_ctrl_proc_tb
module axi_slave_mux
  #(
    parameter FIFO_WIDTH = 64, // AXI4-STREAM data bus width
    parameter DST_WIDTH = 16,  // Width of DST field we are routing on.
    parameter NUM_INPUTS = 2   // number of input AXI buses
    )
    (
     input 				 clk,
     input 				 reset,
     input 				 clear,
     // Inputs
     input [(FIFO_WIDTH*NUM_INPUTS)-1:0] i_tdata,
     input [NUM_INPUTS-1:0] 		 i_tvalid,
     input [NUM_INPUTS-1:0] 		 i_tlast,
     output [NUM_INPUTS-1:0] 		 i_tready,
     // Forwarding Flags
     input [NUM_INPUTS-1:0] 		 forward_valid,
     output reg [NUM_INPUTS-1:0] 	 forward_ack,
     // Output
     output [FIFO_WIDTH-1:0] 		 o_tdata,
     output 				 o_tvalid,
     output 				 o_tlast,
     input 				 o_tready
     );

   wire [FIFO_WIDTH-1:0] i_tdata_array [0:NUM_INPUTS-1];
   
   reg [`LOG2(NUM_INPUTS):0] select;
   reg 			     enable;


   reg 			     state;

   localparam CHECK_THIS_INPUT = 0;
   localparam WAIT_LAST = 1;
   

   always @(posedge clk)
     if (reset | clear) begin
	state <= CHECK_THIS_INPUT;
	select <= 0;
	enable <= 0;
	forward_ack <= 0;	
     end else begin
	case(state)
	  // Is the currently selected input addressing this slave with a ready packet?
	  CHECK_THIS_INPUT:  begin
	     if (forward_valid[select]) begin
		enable <= 1;
		forward_ack[select] <= 1;
		state <= WAIT_LAST;
	     end else if (select == NUM_INPUTS - 1 ) begin
		select <= 0;
	     end else begin
		select <= select + 1;
	     end
	  end
	  // Assert ACK immediately to forwarding logic and then wait for end of packet.
	  WAIT_LAST: begin
	    
	     if (i_tlast[select] && i_tvalid[select] && o_tready) begin
		if (select == NUM_INPUTS - 1 ) begin
		   select <= 0;
		end else begin
		   select <= select + 1;
		end
		state <= CHECK_THIS_INPUT;
		forward_ack <= 0;
		enable <= 0;
	     end else begin
		forward_ack[select] <= 1;
		enable <= 1;
	     end
	  end
	endcase // case(state)
     end
	
   //
   // Combinatorial mux
   //
   genvar m;
     
   generate
      for (m = 0; m < NUM_INPUTS; m = m + 1) begin: form_buses
	 assign i_tdata_array[m] = i_tdata[(m*FIFO_WIDTH)+FIFO_WIDTH-1:m*FIFO_WIDTH];
      end
   endgenerate

   assign 	o_tdata = i_tdata_array[select];
   assign 	o_tvalid = enable && i_tvalid[select];
   assign 	o_tlast = enable && i_tlast[select];
 //  assign 	i_tready = {NUM_INPUTS{o_tready}} & (enable << select);

   generate
      for (m = 0; m < NUM_INPUTS; m = m + 1) begin: form_ready
	 assign i_tready[m] = o_tready && enable && (select == m);
      end
   endgenerate

    
endmodule // axi_slave_mux
module settings_bus_mux #(
  parameter PRIO=0, // 0 = Round robin, 1 = Lower ports get priority (see axi_mux)
  parameter AWIDTH=8,
  parameter DWIDTH=32,
  parameter FIFO_SIZE=1,
  parameter NUM_BUSES=2)
(
  input clk, input reset, input clear,
  input [NUM_BUSES-1:0] in_set_stb, input [NUM_BUSES*AWIDTH-1:0] in_set_addr, input [NUM_BUSES*DWIDTH-1:0] in_set_data,
  output out_set_stb, output [AWIDTH-1:0] out_set_addr, output [DWIDTH-1:0] out_set_data, input ready
);

  wire [NUM_BUSES*(AWIDTH+DWIDTH)-1:0] i_tdata;
  generate
    if(NUM_BUSES <= 1) begin
      assign out_set_stb = in_set_stb;
      assign out_set_addr = in_set_addr;
      assign out_set_data = in_set_data;
    end else begin
      genvar i;
        for (i = 0; i < NUM_BUSES; i = i + 1) begin
          assign i_tdata[(i+1)*(AWIDTH+DWIDTH)-1:i*(AWIDTH+DWIDTH)] = {in_set_addr[(i+1)*AWIDTH-1:i*AWIDTH],in_set_data[(i+1)*DWIDTH-1:i*DWIDTH]};
        end
      axi_mux #(
        .PRIO(PRIO),
        .WIDTH(AWIDTH+DWIDTH),
        .PRE_FIFO_SIZE($clog2(NUM_BUSES)),
        .POST_FIFO_SIZE(FIFO_SIZE),
        .SIZE(NUM_BUSES))
      axi_mux (
        .clk(clk), .reset(reset), .clear(clear),
        .i_tdata(i_tdata), .i_tlast({NUM_BUSES{1'b1}}), .i_tvalid(in_set_stb), .i_tready(),
        .o_tdata({out_set_addr,out_set_data}), .o_tlast(), .o_tvalid(out_set_stb), .o_tready(ready));
    end
  endgenerate
endmodule
module axi_fifo_header
  #(
    parameter WIDTH=64  // Bit width of FIFO word.
    )
    (
     input clk,
     input reset,
     input clear,
     // Monitored FIFO signals
     input [WIDTH-1:0] o_tdata,
     input o_tvalid,
     input o_tready,
     input o_tlast,
     input pkt_present,
     // Header signals
     output reg [WIDTH-1:0] header,
     output reg header_valid
     );

   localparam WAIT_SOF = 0;
   localparam WAIT_EOF = 1;
   
   reg 	    out_state;
   

    //
    // Monitor packets leaving FIFO
    //
    always @(posedge clk)
      if (reset | clear) begin
         out_state <= WAIT_SOF;
      end else
	case(out_state)
	  //
	  // After RESET or the EOF of previous packet, the first cycle with
	  // output valid asserted is the SOF and presents the Header word.
	  // The cycle following the concurrent presentation of asserted output 
	  // valid and output ready presents the word following the header.
	  //
          WAIT_SOF: 
            if (o_tvalid && o_tready) begin
               out_state <= WAIT_EOF;
            end else begin
               out_state <= WAIT_SOF;
            end
	  //
	  // EOF is signalled by o_tlast asserted whilst output valid and ready asserted.
	  //
          WAIT_EOF: 
            if (o_tlast && o_tvalid && o_tready) begin
               out_state <= WAIT_SOF;
            end else begin
               out_state <= WAIT_EOF;
            end
	endcase // case(in_state)
   
   //
   // Pipeline Header signals
   //
   always @(posedge clk)
     if (reset | clear) begin
	header <= 0;
	header_valid <= 0;
     end else if (o_tvalid && (out_state == WAIT_SOF) && pkt_present) begin
	// Header will remian valid until o_tready is asserted as this will cause a state transition.
	header <= o_tdata;
	header_valid <= 1;
     end else begin
	header_valid <= 0;
     end


endmodule // axi_fifo_header
module arb_qualify_master
  #(
    parameter WIDTH=16  // Bit width of destination field.
    )
    (  
       input clk,
       input reset,
       input clear,     
       // Header signals
       input [WIDTH-1:0] header,
       input header_valid,
       // Slave Confg Signals
       input [WIDTH-1:0] slave_addr,
       input [WIDTH-1:0] slave_mask,
       input slave_valid,
       // Arbitration flags
       output reg master_valid,
       input master_ack
       );

   localparam WAIT_HEADER_VALID = 0;
   localparam MATCH = 1;
   localparam WAIT_HEADER_NOT_VALID = 2;
   
   
   reg [1:0] state, next_state;

   
   // Does masked slave address match header field for dest from master?
   assign    header_match = ((header & slave_mask) == (slave_addr & slave_mask)) && slave_valid;
   
   
   always @(posedge clk)
     if (reset | clear) begin
        state <= WAIT_HEADER_VALID;
	master_valid <= 0;
     end else
       begin	  
	  case(state)
	    //
	    // Wait here until Masters FIFO presents a valid header word.
	    //
	    WAIT_HEADER_VALID: begin
	       if (header_valid)
		 if (header_match) begin
		    state <= MATCH;
		    master_valid <= 1;
		 end else
		   next_state <= WAIT_HEADER_NOT_VALID;
	    end
	    //
	    // There should only ever be one match across various arbitors
	    // if they are configured correctly and since the backing FIFO in the
	    // master should not start to drain until the arbitration is won
	    // by that master, master_ack should always preceed de-assertion of
	    // header_valid so we don't check for the other order of deassertion.
	    //
	    MATCH: begin
	       if (master_ack) begin
		  master_valid <= 0;
		  state <= WAIT_HEADER_NOT_VALID;
	       end
	    end
	    //
	    // Wait here until this master starts to drain this packet from his FIFO.
	    //
	    WAIT_HEADER_NOT_VALID: begin
	       if (!header_valid) begin
		  state <= WAIT_HEADER_VALID;
	       end
	    end
	  endcase // case(state)
       end // else: !if(reset | clear)

endmodule // arb_qualify_master
module binary_encoder
#(
      parameter SIZE = 16
)
(
       input [SIZE-1:0] in,
       output [`log2(SIZE)-1:0] out
);

  genvar m,n;

  generate
  // Loop enough times to represent the total number of input bits as an encoded value
  for (m = 0; m <= `log2(SIZE-1); m = m + 1)  begin: expand_or_tree
    wire [SIZE-1:0] encoding;
     // Build enable mask by iterating through every input bit.
     for (n = 0; n < SIZE ; n = n + 1) begin: encode_this_bit
       assign encoding[n] = n[m];
     end
     // OR tree for this output bit with appropriate bits enabled.
     assign out[m] = |(encoding & in);
   end
 endgenerate

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

   (* ASYNC_REG = "TRUE" *) reg [WIDTH-1:0] value[0:STAGES-1];

   integer k;
   initial begin
     for (k = 0; k < STAGES; k = k + 1) begin
       value[k] = INITIAL_VAL;
     end
   end

   genvar i;
   generate
      for (i=0; i<STAGES; i=i+1) begin: stages
         always @(posedge clk) begin
            if (rst) begin
               value[i] <= INITIAL_VAL;
            end else begin
               if (i == 0) begin
                 value[i] <= in;
               end else begin
                 value[i] <= value[i-1];
               end
            end
         end
      end
   endgenerate

   assign out = value[STAGES-1];

endmodule   //synchronizer_impl
module ad5662_auto_spi
(
  input clk,
  input [15:0] dat,
  output reg sclk,
  output reg mosi,
  output reg sync_n
);
  // initialize ldat to 0, thus forcing
  // a reload on init.
  reg [15:0] ldat = 16'd0;
  wire upd = (dat != ldat); // new data present, need to update hw

  reg [23:0] shft=24'b0;
  wire [23:0] nxt_shft;

  // clock cycle counter to throttle generated spi cycles
  // allowing one spi clock cycle every 16 cycles of clk, with clk at 200 MHz
  // gives a spi clock rate of 12 MHz. This can be made more sophisticated
  // or parameterized, if more flexibility in clk is needed, of course.
  reg [3:0] ccnt=4'b0;
  wire [3:0] nxt_ccnt = ccnt + 1'b1;
  wire half = ccnt==4'b1000;
  wire full = ccnt==4'b1111;
  reg sena, hena;
  wire cena;
  always @(posedge clk) if (cena) ccnt <= nxt_ccnt;
  always @(posedge clk) sena <= full; // state updates and rising sclk
  always @(posedge clk) hena <= half; // for falling sclk

  // transfer state counter
  reg [4:0] scnt = 5'b0;
  reg [4:0] nxt_scnt;
  always @(posedge clk) begin
    if (sena) begin
      scnt <= nxt_scnt;
      shft <= nxt_shft;
      mosi <= shft[23];
    end
  end


  // 32 possible states - more than enough to shift-out 24 bits and manage
  // the sync_n line

  // particular scnt values of interest
  localparam READY=5'b00000; // waiting for new data
  localparam DCAPT=5'b00001; // new data transfers into ldat
  localparam SYNCL=5'b00010; // assert sync_n low
  localparam SYNCH=5'b11011; // return sync_n high

  assign cena = upd | scnt != READY;

  always @(scnt or upd)
  begin
    case (scnt)
    READY:
      nxt_scnt = upd ? DCAPT : READY;
    SYNCH:
      nxt_scnt = READY;
    default:
      nxt_scnt = scnt + 1'b1;
    endcase
  end

  // note: defining the power-down mode bits to 00 for "normal operation"
  assign nxt_shft = (scnt == SYNCL) ? { 8'b000000_00, ldat } : { shft[22:0], 1'b0 };

  // Update ldat when dat has changed, but only if READY.
  // Changes to dat arriving faster than can be kept up with here are ignored
  // until the cycle-in-progress is completed.
  wire ldat_ena = sena & (scnt == DCAPT);
  always @(posedge clk) begin
    if (ldat_ena) ldat <= dat;
  end

  // keep the sync_n line low when idle to minimize power consumption
  // it gets brought high just before beginning each transaction
  wire nxt_sync_n = (scnt==SYNCL) | (scnt==SYNCH);
  always @(posedge clk) if (sena) sync_n <= nxt_sync_n;

  reg sclk_go;
  always @(posedge clk) sclk_go <= (scnt > SYNCL);
  wire nxt_sclk = ~sclk_go ? 1'b1 : ~sclk;
  always @(posedge clk) if (sena | hena) sclk <= nxt_sclk;

endmodule
module bin2gray
  #(parameter WIDTH=8)
    (input [WIDTH-1:0] bin,
     output [WIDTH-1:0] gray);

   assign 		gray = (bin >> 1) ^ bin;
   
endmodule // bin2gray
module gpio_atr_io #(
  parameter WIDTH = 32
) (
  input               clk,
  input  [WIDTH-1:0]  gpio_ddr,
  input  [WIDTH-1:0]  gpio_out,
  output [WIDTH-1:0]  gpio_in,
  inout  [WIDTH-1:0]  gpio_pins
);

  //Instantiate registers in the IOB
  (* IOB = "true" *) reg [WIDTH-1:0] gpio_in_iob, gpio_out_iob;
  always @(posedge clk) begin
    gpio_in_iob   <= gpio_pins;
    gpio_out_iob  <= gpio_out;
  end
  assign gpio_in = gpio_in_iob;

  //Pipeline the data direction bus
  reg [WIDTH-1:0] gpio_ddr_reg;
  always @(posedge clk)
    gpio_ddr_reg <= gpio_ddr;

  //Tristate buffers
  genvar i;
  generate for (i=0; i<WIDTH; i=i+1) begin: io_tristate_gen
    assign gpio_pins[i] = gpio_ddr_reg[i] ? gpio_out_iob[i] : 1'bz;
  end endgenerate

endmodule // gpio_atr_io
module pulse_synchronizer #(
  parameter MODE   = "PULSE", // Capture mode {PULSE, POSEDGE, NEGEDGE}
  parameter STAGES = 2        // Number of synchronizer stages
) (
  input   clk_a,    // Clock A
  input   rst_a,    // Reset in clock domain A
  input   pulse_a,  // Pulse in clock domain A to synchronize
  output  busy_a,   // Synchronizer is busy (pulse_a ignored when asserted)
  input   clk_b,    // Clock B
  output  pulse_b   // Pulse in clock domain B
);
  // Trigger logic based on the capture mode
  wire trigger;
  generate if (MODE == "POSEDGE") begin
    reg pulse_a_del_pe = 1'b0;
    always @ (posedge clk_a)
      pulse_a_del_pe <= rst_a ? 1'b0 : pulse_a;
    assign trigger = pulse_a & ~pulse_a_del_pe;
  end else if (MODE == "NEGEDGE") begin
    reg pulse_a_del_ne = 1'b1;
    always @ (posedge clk_a)
      pulse_a_del_ne <= rst_a ? 1'b1 : pulse_a;
    assign trigger = ~pulse_a & pulse_a_del_ne;
  end else begin
    assign trigger = pulse_a;
  end endgenerate

  // Translate pulse/edge to a level and synchronize that into the B domain
  reg pulse_toggle_a = 1'b0;
  always @(posedge clk_a) begin
    pulse_toggle_a <= rst_a ? 1'b0 : (pulse_toggle_a ^ (trigger & ~busy_a));
  end

  wire pulse_toggle_b;
  reg  pulse_toggle_b_del = 1'b0;
  wire handshake_toggle_a;

  synchronizer #(
    .STAGES(STAGES), .INITIAL_VAL(0)
  ) toggle_sync_i (
    .clk(clk_b), .rst(1'b0), .in(pulse_toggle_a), .out(pulse_toggle_b)
  );

  // Handshake toggle signal back into the A domain to deassert busy
  synchronizer #(
    .STAGES(STAGES), .INITIAL_VAL(0)
  ) handshake_sync_i (
    .clk(clk_a), .rst(1'b0), .in(pulse_toggle_b_del), .out(handshake_toggle_a)
  );

  always @(posedge clk_b) begin
    pulse_toggle_b_del <= pulse_toggle_b;
  end

  assign pulse_b = pulse_toggle_b_del ^ pulse_toggle_b;
  assign busy_a = pulse_toggle_a ^ handshake_toggle_a;

endmodule
module setting_reg
  #(parameter my_addr = 0, 
    parameter awidth = 8,
    parameter width = 32,
    parameter at_reset=0)
    (input clk, input rst, input strobe, input wire [awidth-1:0] addr,
     input wire [31:0] in, output reg [width-1:0] out, output reg changed);
   
   always @(posedge clk)
     if(rst)
       begin
	  out <= at_reset;
	  changed <= 1'b0;
       end
     else
       if(strobe & (my_addr==addr))
	 begin
	    out <= in[width-1:0];
	    changed <= 1'b1;
	 end
       else
	 changed <= 1'b0;
   
endmodule // setting_reg
module simple_i2c_core
    #(
        //settings register base address
        parameter BASE = 0,

        //i2c line level at reset
        parameter ARST_LVL = 1
    )
    (
        //clock and synchronous reset
        input clock, input reset,

        //32-bit settings bus inputs
        input set_stb, input [7:0] set_addr, input [31:0] set_data,

        //32-bit data readback
        output reg [31:0] readback,

        //read is high when i2c core can begin another transaction
        output reg ready,

        // I2C signals
        // i2c clock line
        input  scl_pad_i,       // SCL-line input
        output scl_pad_o,       // SCL-line output (always 1'b0)
        output scl_padoen_o,    // SCL-line output enable (active low)

        // i2c data line
        input  sda_pad_i,       // SDA-line input
        output sda_pad_o,       // SDA-line output (always 1'b0)
        output sda_padoen_o,    // SDA-line output enable (active low)

        //optional debug output
        output [31:0] debug
    );

    //declare command settings register
    wire [7:0] sr_what, sr_data;
    wire sr_changed;
    setting_reg #(.my_addr(BASE+0),.width(16)) i2c_cmd_sr(
        .clk(clock),.rst(reset),.strobe(set_stb),.addr(set_addr),.in(set_data),
        .out({sr_what, sr_data}),.changed(sr_changed));

    //declare wb interface signals
    wire [2:0] wb_addr;
    wire [7:0] wb_data_mosi;
    wire [7:0] wb_data_miso;
    wire wb_we, wb_stb, wb_cyc;
    wire wb_ack;

    //create wishbone-based i2c core
    i2c_master_top #(.ARST_LVL(ARST_LVL)) i2c 
     (.wb_clk_i(clock),.wb_rst_i(reset),.arst_i(1'b0), 
      .wb_adr_i(wb_addr),.wb_dat_i(wb_data_mosi),.wb_dat_o(wb_data_miso),
      .wb_we_i(wb_we),.wb_stb_i(wb_stb),.wb_cyc_i(wb_cyc),
      .wb_ack_o(wb_ack),.wb_inta_o(),
      .scl_pad_i(scl_pad_i),.scl_pad_o(scl_pad_o),.scl_padoen_o(scl_padoen_o),
      .sda_pad_i(sda_pad_i),.sda_pad_o(sda_pad_o),.sda_padoen_o(sda_padoen_o) );

    //not ready between setting register and wishbone ack
    always @(posedge clock) begin
        if (reset || wb_ack) ready <= 1;
        else if (sr_changed) ready <= 0;
    end

    //register wishbone data on every ack
    always @(posedge clock) begin
        if (wb_ack) readback <= {24'b0, wb_data_miso};
    end

    //assign wishbone signals
    assign wb_addr = sr_what[2:0];
    assign wb_stb = sr_changed;
    assign wb_we = wb_stb && sr_what[3];
    assign wb_cyc = wb_stb;
    assign wb_data_mosi = sr_data;

endmodule //simple_i2c_core
module priority_encoder_one_hot
#(
  parameter WIDTH = 16
)
(
  input  [WIDTH-1:0]        in,
  output [WIDTH-1:0]        out
);

  wire [WIDTH-1:0] in_rev;
  wire [WIDTH-1:0] in_rev_inv_po = ~in_rev + 1;

  wire [WIDTH-1:0] mask;

  generate
  genvar i,j;

  for (i=0; i<WIDTH; i=i+1)
      assign in_rev[i] = in[WIDTH-1-i];

  for (j=0; j<WIDTH; j=j+1)
      assign mask[j]  = in_rev_inv_po[WIDTH-1-j];
  endgenerate

  assign out = in & mask;

endmodule
module regport_to_settingsbus #(
  parameter BASE   = 14'h0,
  parameter END_ADDR = 14'h3FFF,
  parameter DWIDTH = 32,
  parameter AWIDTH = 14,
  parameter SR_AWIDTH = 12,
  // Dealign for settings bus by shifting by 2
  parameter ADDRESSING = "WORD",
  parameter SHIFT = $clog2(DWIDTH/8)
)(
  input reset,
  input clk,
  input reg_wr_req,
  input [AWIDTH-1:0] reg_wr_addr,
  input [DWIDTH-1:0] reg_wr_data,

  output reg set_stb,
  output reg [SR_AWIDTH-1:0] set_addr,
  output reg [DWIDTH-1:0] set_data
);

  wire set_stb_int;
  wire [DWIDTH-1:0] set_data_int;
  wire [SR_AWIDTH-1:0] set_addr_base;
  wire [SR_AWIDTH-1:0] set_addr_int;

  // Strobe asserted only when address is between BASE and END ADDR
  assign set_stb_int = reg_wr_req && (reg_wr_addr >= BASE) && (reg_wr_addr <= END_ADDR);
  assign set_addr_base = reg_wr_addr - BASE;
  // Shift by 2 in case of setting bus
  assign set_addr_int = (ADDRESSING == "WORD") ? {{SHIFT{1'b0}}, set_addr_base[SR_AWIDTH-1:SHIFT]}
                                               : set_addr_base[SR_AWIDTH-1:0];
  assign set_data_int = reg_wr_data;

  // Adding a pipeline stage
  always @(posedge clk) begin
    if (reset) begin
      set_stb  <= 'b0;
      set_addr <= 'h0;
      set_data <= 'h0;
    end else begin
      set_stb  <= set_stb_int;
      set_addr <= set_addr_int;
      set_data <= set_data_int;
    end
  end

endmodule // regport_to_settingsbus
module user_settings
  #(parameter BASE=0)
  (input clk,
   input rst,

   input         set_stb,
   input [7:0]   set_addr,
   input [31:0]  set_data,

   output        set_stb_user,
   output [7:0]  set_addr_user,
   output [31:0] set_data_user
   );

   wire 	 addr_changed, data_changed;
   reg 		 stb_int;
   
   setting_reg #(.my_addr(BASE+0),.width(8)) sr_0
     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
      .in(set_data),.out(set_addr_user),.changed(addr_changed) );
   
   setting_reg #(.my_addr(BASE+1)) sr_1
     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
      .in(set_data),.out(set_data_user),.changed(data_changed) );
   
   always @(posedge clk)
     if (rst|set_stb_user)
       stb_int <= 0;
     else
       if (addr_changed)
         stb_int <= 1;
   
   assign set_stb_user = stb_int & data_changed;
   
endmodule // user_settings
module gray2bin #(
    parameter WIDTH = 8)
(
    input [WIDTH-1:0] gray,
    output reg [WIDTH-1:0] bin
);

    integer i;
    always @(*) begin
        bin[WIDTH-1] = gray[WIDTH-1];
        for (i = WIDTH-2; i >= 0; i = i - 1) begin
            bin[i] = bin[i+1] ^ gray[i];
        end
    end

endmodule
module por_gen
  (input clk,
   output reset_out);

   reg 		por_rst;
   reg [7:0] 	por_counter = 8'h0;

   always @(posedge clk)
     if (por_counter != 8'h55)
       begin
          por_counter <= por_counter + 8'h1;
          por_rst <= 1'b1;
       end
     else
       por_rst <= 1'b0;

   assign reset_out = por_rst;

endmodule // por_gen
module filter_bad_sid
  (
   input clk,
   input reset,
   input clear,
   //
   input [64:0] i_tdata,
   input i_tvalid,
   output i_tready,
   //
   output [64:0] o_tdata,
   output o_tvalid,
   input  o_tready,
   //
   output reg [15:0] count
   );

   reg [1:0] state;
   wire      good_sid;
   wire      qualify_i_tvalid;
   
   localparam IDLE = 0;
   localparam ACCEPT = 1;
   localparam DISCARD = 2;
   

   always @(posedge clk)
     if (reset | clear) begin
	state <= IDLE;
	count <= 0;
     end else
       case(state)
	 //
	 IDLE: begin
	    if  (i_tvalid && i_tready)
	      if (good_sid)
		state <= ACCEPT;
	      else begin
		 count <= count + 1;
		 state <= DISCARD;
	      end	    
	 end
	 //
	 ACCEPT: begin
	    if (i_tvalid && i_tready && i_tdata[64]) 
	      state <= IDLE;
	 end
	 //
	 DISCARD: begin
	    if (i_tvalid && i_tready && i_tdata[64]) 
	      state <= IDLE;
	 end
       endcase // case(state)
   
   assign good_sid = ((i_tdata[15:0] == 16'h00A0) || (i_tdata[15:0] == 16'h00B0));
   
   assign qualify_i_tvalid = (state == IDLE) ? good_sid : ((state == DISCARD) ? 1'b0 : 1'b1);

   //
   // Buffer output, break combinatorial timing paths
   //
   axi_fifo_short #(.WIDTH(65)) fifo_short
     (
      .clk(clk), .reset(reset), .clear(clear),
      .i_tdata(i_tdata), .i_tvalid(i_tvalid && qualify_i_tvalid), .i_tready(i_tready),
      .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready),
      .space(), .occupied()
      );
   
endmodule // filter_bad_sid
module regport_to_xbar_settingsbus #(
  parameter BASE   = 14'h0,
  parameter END_ADDR = 14'h3FFF,
  parameter DWIDTH = 32,
  parameter AWIDTH = 14,
  parameter SR_AWIDTH = 12,
  // Dealign for settings bus by shifting by 2
  parameter ADDRESSING = "WORD",
  parameter SHIFT = $clog2(DWIDTH/8)
  )(
  input                   clk,
  input                   reset,

  input                   reg_wr_req,
  input [AWIDTH-1:0]      reg_wr_addr,
  input [DWIDTH-1:0]      reg_wr_data,

  input                   reg_rd_req,
  input [AWIDTH-1:0]      reg_rd_addr,
  output [DWIDTH-1:0]     reg_rd_data,
  output                  reg_rd_resp,

  output                  set_stb,
  output [SR_AWIDTH-1:0]  set_addr,
  output [DWIDTH-1:0]     set_data,

  output                  rb_stb,
  output [SR_AWIDTH-1:0]  rb_addr,
  input  [DWIDTH-1:0]     rb_data
);

  reg               reg_rd_req_delay;
  reg               reg_rd_req_delay2;
  wire [AWIDTH-1:0] set_addr_int;
  reg [AWIDTH-1:0]  rb_addr_int;

  always @(posedge clk) begin
    if (reset) begin
      reg_rd_req_delay <= 1'b0;
      reg_rd_req_delay2 <= 1'b0;
      rb_addr_int     <= 'd0;
    end
    else if (reg_rd_req) begin
      rb_addr_int <= reg_rd_addr - BASE;
      reg_rd_req_delay <= 1'b1;
    end
    else if (reg_rd_req_delay) begin
      reg_rd_req_delay2 <= 1'b1;
      reg_rd_req_delay <= 1'b0;
    end
    // Deassert after two clock cycles
    else if (reg_rd_req_delay2) begin
      reg_rd_req_delay <= 1'b0;
      reg_rd_req_delay2 <= 1'b0;
      rb_addr_int     <= 'd0;
    end
    else begin
      reg_rd_req_delay <= 1'b0;
      reg_rd_req_delay2 <= 1'b0;
      rb_addr_int     <= 'd0;
    end
  end

  // Write mode of settings bus
  regport_to_settingsbus #(
    .BASE(BASE),
    .END_ADDR(END_ADDR),
    .DWIDTH(DWIDTH),
    .AWIDTH(AWIDTH),
    .SR_AWIDTH(SR_AWIDTH),
    .ADDRESSING(ADDRESSING)
   ) xbar_write_settings_bus (
    .clk(clk),
    .reset(reset),
    .reg_wr_req(reg_wr_req),
    .reg_wr_addr(reg_wr_addr),
    .reg_wr_data(reg_wr_data),

    .set_stb(set_stb),
    .set_addr(set_addr),
    .set_data(set_data)
  );

  assign rb_addr = (ADDRESSING == "WORD") ? {{SHIFT{1'b0}}, rb_addr_int[SR_AWIDTH-1:SHIFT]}
                                          : rb_addr_int[SR_AWIDTH-1:0];
  // Strobe asserted two cycle after read request only when address is between BASE and END ADDR
  // This is specific to the xbar as the xbar delays read data by an extra clock
  // cycle to relax timing.
  assign rb_stb  = reg_rd_req_delay2 && (reg_rd_addr >= BASE) && (reg_rd_addr <= END_ADDR);
  assign reg_rd_resp = rb_stb;
  assign reg_rd_data = rb_data;

endmodule
module priority_encoder
#(
  parameter WIDTH = 16
)
(
  input  [WIDTH-1:0]        in,
  output [`log2(WIDTH)-1:0] out
);

  wire [WIDTH-1:0] one_hot;

  // the priority encoder spits out the position
  // of the leading bit as one hot coding
  priority_encoder_one_hot #
  (
    .WIDTH(WIDTH)
  )
  prio_one_hot0
  (
    .in(in),
    .out(one_hot)
  );

  // binary encoder turns the one hot coding
  // into binary encoding
  binary_encoder #
  (
    .WIDTH(WIDTH)
  )
  binary_enc0
  (
    .in(one_hot),
    .out(out)
  );
endmodule