dakies/OSS_Verilog huggingface dataset:
module util_axis_resize # (

  parameter MASTER_DATA_WIDTH = 64,
  parameter SLAVE_DATA_WIDTH = 64,
  parameter BIG_ENDIAN = 0)(

  input                       clk,
  input                       resetn,

  input                       s_valid,
  output                      s_ready,
  input [SLAVE_DATA_WIDTH-1:0]  s_data,

  output                      m_valid,
  input                       m_ready,
  output [MASTER_DATA_WIDTH-1:0] m_data
);

localparam RATIO = (SLAVE_DATA_WIDTH < MASTER_DATA_WIDTH) ?
                            MASTER_DATA_WIDTH / SLAVE_DATA_WIDTH :
                            SLAVE_DATA_WIDTH / MASTER_DATA_WIDTH;

function integer clog2;
  input integer value;
  begin
    value = value-1;
  for (clog2=0; value>0; clog2=clog2+1)
    value = value>>1;
  end
endfunction

generate if (SLAVE_DATA_WIDTH == MASTER_DATA_WIDTH) begin

assign m_valid = s_valid;
assign s_ready = m_ready;
assign m_data = s_data;

end else if (SLAVE_DATA_WIDTH < MASTER_DATA_WIDTH) begin

reg [MASTER_DATA_WIDTH-1:0] data;
reg [clog2(RATIO)-1:0] count;
reg valid;

always @(posedge clk)
begin
  if (resetn == 1'b0) begin
    count <= RATIO - 1;
    valid <= 1'b0;
  end else begin
    if (count == 'h00 && s_ready == 1'b1 && s_valid == 1'b1)
      valid <= 1'b1;
    else if (m_ready == 1'b1)
      valid <= 1'b0;

    if (s_ready == 1'b1 && s_valid == 1'b1) begin
      if (count == 'h00)
        count <= RATIO - 1;
      else
        count <= count - 1'b1;
    end
  end
end

always @(posedge clk)
begin
  if (s_ready == 1'b1 && s_valid == 1'b1)
    if (BIG_ENDIAN == 1) begin
      data <= {data[MASTER_DATA_WIDTH-SLAVE_DATA_WIDTH-1:0], s_data};
    end else begin
      data <= {s_data, data[MASTER_DATA_WIDTH-1:SLAVE_DATA_WIDTH]};
    end
end

assign s_ready = ~valid || m_ready;
assign m_valid = valid;
assign m_data = data;

end else begin

reg [SLAVE_DATA_WIDTH-1:0] data;
reg [clog2(RATIO)-1:0] count;
reg valid;

always @(posedge clk)
begin
  if (resetn == 1'b0) begin
    count <= RATIO - 1;
    valid <= 1'b0;
  end else begin
    if (s_valid == 1'b1 && s_ready == 1'b1)
      valid <= 1'b1;
    else if (count == 'h0 && m_ready == 1'b1 && m_valid == 1'b1)
      valid <= 1'b0;

    if (m_ready == 1'b1 && m_valid == 1'b1) begin
      if (count == 'h00)
        count <= RATIO - 1;
      else
        count <= count - 1'b1;
    end
  end
end

always @(posedge clk)
begin
  if (s_ready == 1'b1 && s_valid == 1'b1) begin
    data <= s_data;
  end else if (m_ready == 1'b1 && m_valid == 1'b1) begin
    if (BIG_ENDIAN == 1) begin
      data[SLAVE_DATA_WIDTH-1:MASTER_DATA_WIDTH] <= data[SLAVE_DATA_WIDTH-MASTER_DATA_WIDTH-1:0];
    end else begin
      data[SLAVE_DATA_WIDTH-MASTER_DATA_WIDTH-1:0] <= data[SLAVE_DATA_WIDTH-1:MASTER_DATA_WIDTH];
    end
  end
end

assign s_ready = ~valid || (m_ready && count == 'h0);
assign m_valid = valid;
assign m_data = BIG_ENDIAN == 1 ?
  data[SLAVE_DATA_WIDTH-1:SLAVE_DATA_WIDTH-MASTER_DATA_WIDTH] :
  data[MASTER_DATA_WIDTH-1:0];

end
endgenerate

endmodule
module axi_gpreg_io #(

  parameter   ID = 0) (

  // gpio

  output  reg [31:0]      up_gp_ioenb,
  output  reg [31:0]      up_gp_out,
  input       [31:0]      up_gp_in,

  // bus interface

  input                   up_rstn,
  input                   up_clk,
  input                   up_wreq,
  input       [13:0]      up_waddr,
  input       [31:0]      up_wdata,
  output  reg             up_wack,
  input                   up_rreq,
  input       [13:0]      up_raddr,
  output  reg [31:0]      up_rdata,
  output  reg             up_rack);


  // internal registers

  // internal signals

  wire            up_wreq_s;
  wire            up_rreq_s;

  // decode block select

  assign up_wreq_s = (up_waddr[13:4] == ID) ? up_wreq : 1'b0;
  assign up_rreq_s = (up_raddr[13:4] == ID) ? up_rreq : 1'b0;

  // processor write interface

  always @(negedge up_rstn or posedge up_clk) begin
    if (up_rstn == 0) begin
      up_wack <= 'd0;
      up_gp_ioenb <= {32{1'b1}};
      up_gp_out <= 'd0;
    end else begin
      up_wack <= up_wreq_s;
      if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h0)) begin
        up_gp_ioenb <= up_wdata;
      end
      if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h1)) begin
        up_gp_out <= up_wdata;
      end
    end
  end

  // processor read interface

  always @(negedge up_rstn or posedge up_clk) begin
    if (up_rstn == 0) begin
      up_rack <= 'd0;
      up_rdata <= 'd0;
    end else begin
      up_rack <= up_rreq_s;
      if (up_rreq_s == 1'b1) begin
        case (up_raddr[3:0])
          4'b0000: up_rdata <= up_gp_ioenb;
          4'b0001: up_rdata <= up_gp_out;
          4'b0010: up_rdata <= up_gp_in;
          default: up_rdata <= 32'd0;
        endcase
      end else begin
        up_rdata <= 32'd0;
      end
    end
  end

endmodule
module axi_gpreg_clock_mon #(

  parameter   ID = 0,
  parameter   BUF_ENABLE = 0) (

  // clock

  input                   d_clk,

  // bus interface

  input                   up_rstn,
  input                   up_clk,
  input                   up_wreq,
  input       [13:0]      up_waddr,
  input       [31:0]      up_wdata,
  output  reg             up_wack,
  input                   up_rreq,
  input       [13:0]      up_raddr,
  output  reg [31:0]      up_rdata,
  output  reg             up_rack);


  // internal registers

  reg             up_d_preset = 'd0;
  reg             up_d_resetn = 'd0;

  // internal signals

  wire            up_wreq_s;
  wire            up_rreq_s;
  wire    [31:0]  up_d_count_s;
  wire            d_rst;
  wire            d_clk_g;

  // decode block select

  assign up_wreq_s = (up_waddr[13:4] == ID) ? up_wreq : 1'b0;
  assign up_rreq_s = (up_raddr[13:4] == ID) ? up_rreq : 1'b0;

  // processor write interface

  always @(negedge up_rstn or posedge up_clk) begin
    if (up_rstn == 0) begin
      up_d_preset <= 1'd1;
      up_wack <= 'd0;
      up_d_resetn <= 'd0;
    end else begin
      up_d_preset <= ~up_d_resetn;
      up_wack <= up_wreq_s;
      if ((up_wreq_s == 1'b1) && (up_waddr[3:0] == 4'h0)) begin
        up_d_resetn <= up_wdata[0];
      end
    end
  end

  // processor read interface

  always @(negedge up_rstn or posedge up_clk) begin
    if (up_rstn == 0) begin
      up_rack <= 'd0;
      up_rdata <= 'd0;
    end else begin
      up_rack <= up_rreq_s;
      if (up_rreq_s == 1'b1) begin
        case (up_raddr[3:0])
          4'b0000: up_rdata <= {31'd0, up_d_resetn};
          4'b0010: up_rdata <= up_d_count_s;
          default: up_rdata <= 32'd0;
        endcase
      end else begin
        up_rdata <= 32'd0;
      end
    end
  end

  // clock monitor

  up_clock_mon i_clock_mon (
    .up_rstn (up_rstn),
    .up_clk (up_clk),
    .up_d_count (up_d_count_s),
    .d_rst (d_rst),
    .d_clk (d_clk_g));

  ad_rst i_d_rst_reg (
    .rst_async (up_d_preset),
    .clk (d_clk_g),
    .rstn (),
    .rst (d_rst));

  generate
  if (BUF_ENABLE == 1) begin
  BUFG i_bufg (
    .I (d_clk),
    .O (d_clk_g));
  end else begin
  assign d_clk_g = d_clk;
  end
  endgenerate

endmodule
module delay
//----------- Parameters Declarations -------------------------------------------
#(
    parameter DELAY = 128
)
//----------- Ports Declarations -----------------------------------------------
(
    input       clk_i,
    input       rst_n_i,
    input       sig_i,
    output reg  sig_o
);
//------------------------------------------------------------------------------
//----------- Registers Declarations -------------------------------------------
//------------------------------------------------------------------------------
reg [DELAY-1:0] shift_reg;

//------------------------------------------------------------------------------
//----------- Assign/Always Blocks ---------------------------------------------
//------------------------------------------------------------------------------
always @(posedge clk_i)
begin
    if(rst_n_i == 0)
    begin
        shift_reg   <= 0;
        sig_o       <= 0;
    end
    else
    begin
        shift_reg   <= {shift_reg[DELAY-2:0], sig_i};
        sig_o       <= shift_reg[DELAY-1];
    end
end

endmodule
module axi_ad9265_if #(

  parameter   FPGA_TECHNOLOGY = 0,
  parameter   IO_DELAY_GROUP = "adc_if_delay_group",
  parameter   DELAY_REFCLK_FREQUENCY = 200) (

  // adc interface (clk, data, over-range)
  // nominal clock 125 MHz, up to 300 MHz

  input                   adc_clk_in_p,
  input                   adc_clk_in_n,
  input       [ 7:0]      adc_data_in_p,
  input       [ 7:0]      adc_data_in_n,
  input                   adc_or_in_p,
  input                   adc_or_in_n,

  // interface outputs

  output                  adc_clk,
  output  reg [15:0]      adc_data,
  output  reg             adc_or,
  output  reg             adc_status,

  // delay control signals

  input                   up_clk,
  input       [ 8:0]      up_dld,
  input       [44:0]      up_dwdata,
  output      [44:0]      up_drdata,
  input                   delay_clk,
  input                   delay_rst,
  output                  delay_locked);


  // internal registers

  reg     [ 7:0]  adc_data_p = 'd0;
  reg     [ 7:0]  adc_data_n = 'd0;
  reg             adc_or_p = 'd0;
  reg             adc_or_n = 'd0;

  // internal signals

  wire    [ 7:0]  adc_data_p_s;
  wire    [ 7:0]  adc_data_n_s;
  wire            adc_or_p_s;
  wire            adc_or_n_s;

  genvar          l_inst;

  always @(posedge adc_clk)
  begin
    adc_status <= 1'b1;
    adc_or <= adc_or_p_s | adc_or_n_s;
    adc_data <= { adc_data_p_s[7], adc_data_n_s[7], adc_data_p_s[6], adc_data_n_s[6], adc_data_p_s[5], adc_data_n_s[5], adc_data_p_s[4], adc_data_n_s[4], adc_data_p_s[3], adc_data_n_s[3], adc_data_p_s[2], adc_data_n_s[2], adc_data_p_s[1], adc_data_n_s[1], adc_data_p_s[0], adc_data_n_s[0]};
  end

  // data interface

  generate
  for (l_inst = 0; l_inst <= 7; l_inst = l_inst + 1) begin : g_adc_if
  ad_data_in #(
    .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY),
    .IODELAY_CTRL (0),
    .IODELAY_GROUP (IO_DELAY_GROUP),
    .REFCLK_FREQUENCY (DELAY_REFCLK_FREQUENCY))
  i_adc_data (
    .rx_clk (adc_clk),
    .rx_data_in_p (adc_data_in_p[l_inst]),
    .rx_data_in_n (adc_data_in_n[l_inst]),
    .rx_data_p (adc_data_p_s[l_inst]),
    .rx_data_n (adc_data_n_s[l_inst]),
    .up_clk (up_clk),
    .up_dld (up_dld[l_inst]),
    .up_dwdata (up_dwdata[((l_inst*5)+4):(l_inst*5)]),
    .up_drdata (up_drdata[((l_inst*5)+4):(l_inst*5)]),
    .delay_clk (delay_clk),
    .delay_rst (delay_rst),
    .delay_locked ());
  end
  endgenerate

  // over-range interface

  ad_data_in #(
    .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY),
    .IODELAY_CTRL (1),
    .IODELAY_GROUP (IO_DELAY_GROUP),
    .REFCLK_FREQUENCY (DELAY_REFCLK_FREQUENCY))
  i_adc_or (
    .rx_clk (adc_clk),
    .rx_data_in_p (adc_or_in_p),
    .rx_data_in_n (adc_or_in_n),
    .rx_data_p (adc_or_p_s),
    .rx_data_n (adc_or_n_s),
    .up_clk (up_clk),
    .up_dld (up_dld[8]),
    .up_dwdata (up_dwdata[44:40]),
    .up_drdata (up_drdata[44:40]),
    .delay_clk (delay_clk),
    .delay_rst (delay_rst),
    .delay_locked (delay_locked));

  // clock

  ad_data_clk
  i_adc_clk (
    .rst (1'b0),
    .locked (),
    .clk_in_p (adc_clk_in_p),
    .clk_in_n (adc_clk_in_n),
    .clk (adc_clk));

endmodule
module axi_ad9162_if (

  // jesd interface
  // tx_clk is (line-rate/40)

  input                   tx_clk,
  output  reg [255:0]     tx_data,

  // dac interface

  output                  dac_clk,
  input                   dac_rst,
  input       [255:0]     dac_data);

  // reorder data for the jesd links

  assign dac_clk = tx_clk;

  always @(posedge tx_clk) begin
    tx_data[255:248] <= dac_data[247:240];
    tx_data[247:240] <= dac_data[183:176];
    tx_data[239:232] <= dac_data[119:112];
    tx_data[231:224] <= dac_data[ 55: 48];
    tx_data[223:216] <= dac_data[255:248];
    tx_data[215:208] <= dac_data[191:184];
    tx_data[207:200] <= dac_data[127:120];
    tx_data[199:192] <= dac_data[ 63: 56];
    tx_data[191:184] <= dac_data[231:224];
    tx_data[183:176] <= dac_data[167:160];
    tx_data[175:168] <= dac_data[103: 96];
    tx_data[167:160] <= dac_data[ 39: 32];
    tx_data[159:152] <= dac_data[239:232];
    tx_data[151:144] <= dac_data[175:168];
    tx_data[143:136] <= dac_data[111:104];
    tx_data[135:128] <= dac_data[ 47: 40];
    tx_data[127:120] <= dac_data[215:208];
    tx_data[119:112] <= dac_data[151:144];
    tx_data[111:104] <= dac_data[ 87: 80];
    tx_data[103: 96] <= dac_data[ 23: 16];
    tx_data[ 95: 88] <= dac_data[223:216];
    tx_data[ 87: 80] <= dac_data[159:152];
    tx_data[ 79: 72] <= dac_data[ 95: 88];
    tx_data[ 71: 64] <= dac_data[ 31: 24];
    tx_data[ 63: 56] <= dac_data[199:192];
    tx_data[ 55: 48] <= dac_data[135:128];
    tx_data[ 47: 40] <= dac_data[ 71: 64];
    tx_data[ 39: 32] <= dac_data[  7:  0];
    tx_data[ 31: 24] <= dac_data[207:200];
    tx_data[ 23: 16] <= dac_data[143:136];
    tx_data[ 15:  8] <= dac_data[ 79: 72];
    tx_data[  7:  0] <= dac_data[ 15:  8];
  end

endmodule
module util_fir_dec (
  input               aclk,
  input               s_axis_data_tvalid,
  output              s_axis_data_tready,
  input       [15:0]  channel_0,
  input       [15:0]  channel_1,
  input               decimate,
  output              m_axis_data_tvalid,
  output      [31:0]  m_axis_data_tdata);

  wire [31:0] s_axis_data_tdata;

  wire        m_axis_data_tvalid_s;
  wire [31:0] m_axis_data_tdata_s;

  assign s_axis_data_tdata = {channel_1, channel_0};

  assign m_axis_data_tvalid = (decimate == 1'b1) ? m_axis_data_tvalid_s : s_axis_data_tvalid;
  assign m_axis_data_tdata = (decimate == 1'b1) ? {m_axis_data_tdata_s[30:16], 1'b0, m_axis_data_tdata_s[14:0], 1'b0} : {channel_1, channel_0};

  fir_decim decimator (
    .aclk(aclk),
    .s_axis_data_tvalid(s_axis_data_tvalid),
    .s_axis_data_tready(s_axis_data_tready),
    .s_axis_data_tdata(s_axis_data_tdata),
    .m_axis_data_tvalid(m_axis_data_tvalid_s),
    .m_axis_data_tdata(m_axis_data_tdata_s)
  );

endmodule  // util_fir_dec
module mdc_mdio #(

  parameter PHY_AD = 5'b10000) (

  input                   mdio_mdc,
  input                   mdio_in_w,
  input                   mdio_in_r,

  output  reg [ 1:0]      speed_select,
  output  reg             duplex_mode);


  localparam IDLE     = 2'b01;
  localparam ACQUIRE  = 2'b10;

  wire        preamble;

  reg [ 1:0]  current_state = IDLE;
  reg [ 1:0]  next_state    = IDLE;
  reg [31:0]  data_in       = 32'h0;
  reg [31:0]  data_in_r     = 32'h0;
  reg [ 5:0]  data_counter  = 6'h0;

  assign preamble = &data_in;

  always @(posedge mdio_mdc) begin
    current_state <= next_state;
    data_in <= {data_in[30:0], mdio_in_w};
    if (current_state == ACQUIRE) begin
      data_counter <= data_counter + 1;
    end else begin
      data_counter <= 0;
    end
    if (data_counter == 6'h1f) begin
      if (data_in[31] == 1'b0 && data_in[29:28]==2'b10 && data_in[27:23] == PHY_AD && data_in[22:18] == 5'h11) begin
        speed_select <= data_in_r[16:15] ;
        duplex_mode  <= data_in_r[14];
      end
    end
  end

  always @(negedge mdio_mdc) begin
    data_in_r <= {data_in_r[30:0], mdio_in_r};
  end

  always @(*) begin
    case (current_state)
      IDLE: begin
        if (preamble == 1 && mdio_in_w == 0) begin
          next_state <= ACQUIRE;
        end else begin
          next_state <= IDLE;
        end
      end
      ACQUIRE: begin
        if (data_counter == 6'h1f) begin
          next_state <= IDLE;
        end else begin
          next_state <= ACQUIRE;
        end
      end
      default: begin
        next_state <= IDLE;
      end
    endcase
  end

endmodule
module axi_ad9467_channel#(

  parameter CHANNEL_ID = 0) (

  // adc interface

  input                   adc_clk,
  input                   adc_rst,
  input       [15:0]      adc_data,
  input                   adc_or,

  // channel interface

  output      [15:0]      adc_dfmt_data,
  output                  adc_enable,
  output                  up_adc_pn_err,
  output                  up_adc_pn_oos,
  output                  up_adc_or,

  // processor interface

  input                   up_rstn,
  input                   up_clk,
  input                   up_wreq,
  input       [13:0]      up_waddr,
  input       [31:0]      up_wdata,
  output                  up_wack,
  input                   up_rreq,
  input       [13:0]      up_raddr,
  output      [31:0]      up_rdata,
  output                  up_rack);


  // internal signals

  wire            adc_pn_oos_s;
  wire            adc_pn_err_s;
  wire    [ 3:0]  adc_pnseq_sel_s;
  wire            adc_dfmt_enable_s;
  wire            adc_dfmt_type_s;
  wire            adc_dfmt_se_s;

  // instantiations

  axi_ad9467_pnmon i_axi_ad9467_pnmon (
    .adc_clk (adc_clk),
    .adc_data (adc_data),
    .adc_pn_oos (adc_pn_oos_s),
    .adc_pn_err (adc_pn_err_s),
    .adc_pnseq_sel (adc_pnseq_sel_s));

  ad_datafmt #(.DATA_WIDTH(16)) i_datafmt (
    .clk(adc_clk),
    .valid(1'b1),
    .data(adc_data),
    .valid_out(),
    .data_out(adc_dfmt_data),
    .dfmt_enable(adc_dfmt_enable_s),
    .dfmt_type(adc_dfmt_type_s),
    .dfmt_se(adc_dfmt_se_s));

  up_adc_channel #(
    .COMMON_ID (6'h01),
    .CHANNEL_ID(CHANNEL_ID),
    .USERPORTS_DISABLE (0),
    .DATAFORMAT_DISABLE (0),
    .DCFILTER_DISABLE (0),
    .IQCORRECTION_DISABLE (0))
  i_up_adc_channel (
    .adc_clk (adc_clk),
    .adc_rst (adc_rst),
    .adc_enable (adc_enable),
    .adc_iqcor_enb (),
    .adc_dcfilt_enb (),
    .adc_dfmt_se (adc_dfmt_se_s),
    .adc_dfmt_type (adc_dfmt_type_s),
    .adc_dfmt_enable (adc_dfmt_enable_s),
    .adc_dcfilt_offset (),
    .adc_dcfilt_coeff (),
    .adc_iqcor_coeff_1 (),
    .adc_iqcor_coeff_2 (),
    .adc_pnseq_sel (adc_pnseq_sel_s),
    .adc_data_sel (),
    .adc_pn_err (adc_pn_err_s),
    .adc_pn_oos (adc_pn_oos_s),
    .adc_or (adc_or),
    .up_adc_pn_err (up_adc_pn_err),
    .up_adc_pn_oos (up_adc_pn_oos),
    .up_adc_or (up_adc_or),
    .up_usr_datatype_be (),
    .up_usr_datatype_signed (),
    .up_usr_datatype_shift (),
    .up_usr_datatype_total_bits (),
    .up_usr_datatype_bits (),
    .up_usr_decimation_m (),
    .up_usr_decimation_n (),
    .adc_usr_datatype_be (1'b0),
    .adc_usr_datatype_signed (1'b1),
    .adc_usr_datatype_shift (8'd0),
    .adc_usr_datatype_total_bits (8'd16),
    .adc_usr_datatype_bits (8'd16),
    .adc_usr_decimation_m (16'd1),
    .adc_usr_decimation_n (16'd1),
    .up_rstn (up_rstn),
    .up_clk (up_clk),
    .up_wreq (up_wreq),
    .up_waddr (up_waddr),
    .up_wdata (up_wdata),
    .up_wack (up_wack),
    .up_rreq (up_rreq),
    .up_raddr (up_raddr),
    .up_rdata (up_rdata),
    .up_rack (up_rack));

endmodule
module util_extract #(

  parameter  NUM_OF_CHANNELS = 2,
  parameter  DATA_WIDTH = NUM_OF_CHANNELS * 16) (

  input                         clk,

  input       [DATA_WIDTH-1:0]  data_in,
  input       [DATA_WIDTH-1:0]  data_in_trigger,
  input                         data_valid,

  output      [DATA_WIDTH-1:0]  data_out,
  output reg                    valid_out,
  output reg                    trigger_out
);

  // loop variables

  genvar  n;

  reg trigger_d1;

  wire [15:0] trigger; // 16 maximum channels

  generate
  for (n = 0; n < NUM_OF_CHANNELS; n = n + 1) begin: g_data_out
    assign data_out[(n+1)*16-1:n*16] = {data_in[(n*16)+14],data_in[(n*16)+14:n*16]};
    assign trigger[n] = data_in_trigger[(16*n)+15];
  end
  for (n = NUM_OF_CHANNELS; n < 16; n = n + 1) begin: g_trigger_out
    assign trigger[n] = 1'b0;
  end
  endgenerate

  // compensate delay in the FIFO
  always @(posedge clk) begin
    valid_out  <= data_valid;
    if (data_valid == 1'b1) begin
      trigger_d1  <= |trigger;
      trigger_out <= trigger_d1;
    end
  end

endmodule
module axi_ad9963_rx_pnmon (

  // adc interface

  input           adc_clk,
  input           adc_valid,
  input   [11:0]  adc_data,

  // pn out of sync and error

  input   [ 3:0]  adc_pnseq_sel,
  output          adc_pn_oos,
  output          adc_pn_err);

  // internal registers

  reg     [23:0]  adc_pn_data_in = 'd0;
  reg     [23:0]  adc_pn_data_pn = 'd0;

  // internal signals

  wire    [31:0]  adc_pn_data_pn_s;

  // bit reversal function

  function [11:0] brfn;
    input [11:0] din;
    reg   [11:0] dout;
    begin
      dout[11] = din[ 0];
      dout[10] = din[ 1];
      dout[ 9] = din[ 2];
      dout[ 8] = din[ 3];
      dout[ 7] = din[ 4];
      dout[ 6] = din[ 5];
      dout[ 5] = din[ 6];
      dout[ 4] = din[ 7];
      dout[ 3] = din[ 8];
      dout[ 2] = din[ 9];
      dout[ 1] = din[10];
      dout[ 0] = din[11];
      brfn = dout;
    end
  endfunction

  // standard prbs functions

 function [23:0] pn23;
    input [23:0] din;
    reg   [23:0] dout;
    begin
      dout = {din[22:0], din[22] ^ din[17]};
      pn23 = dout;
    end
  endfunction

  // standard, runs on 24bit

  assign adc_pn_data_pn_s = (adc_pn_oos == 1'b1) ? adc_pn_data_in : adc_pn_data_pn;

 always @(posedge adc_clk) begin
   if(adc_valid == 1'b1) begin
     adc_pn_data_in <= {adc_pn_data_in[22:11], adc_data};
     adc_pn_data_pn <= pn23(adc_pn_data_pn_s);
   end
 end

  // pn oos & pn err

  ad_pnmon #(.DATA_WIDTH(24)) i_pnmon (
    .adc_clk (adc_clk),
    .adc_valid_in (adc_valid),
    .adc_data_in (adc_pn_data_in),
    .adc_data_pn (adc_pn_data_pn),
    .adc_pattern_has_zero (1'b0),
    .adc_pn_oos (adc_pn_oos),
    .adc_pn_err (adc_pn_err));

endmodule
module fifo_address_sync #(
  parameter ADDRESS_WIDTH = 4
) (
  input clk,
  input resetn,

  input m_axis_ready,
  output reg m_axis_valid,
  output reg  [ADDRESS_WIDTH-1:0] m_axis_raddr,
  output [ADDRESS_WIDTH:0] m_axis_level,

  output reg s_axis_ready,
  input s_axis_valid,
  output reg s_axis_empty,
  output reg [ADDRESS_WIDTH-1:0] s_axis_waddr,
  output [ADDRESS_WIDTH:0] s_axis_room
);

localparam MAX_ROOM = {1'b1,{ADDRESS_WIDTH{1'b0}}};

reg [ADDRESS_WIDTH:0] room = MAX_ROOM;
reg [ADDRESS_WIDTH:0] level = 'h00;
reg [ADDRESS_WIDTH:0] level_next;

assign s_axis_room = room;
assign m_axis_level = level;

wire read = m_axis_ready & m_axis_valid;
wire write = s_axis_ready & s_axis_valid;

always @(posedge clk)
begin
  if (resetn == 1'b0) begin
    s_axis_waddr <= 'h00;
    m_axis_raddr <= 'h00;
  end else begin
    if (write)
      s_axis_waddr <= s_axis_waddr + 1'b1;
    if (read)
      m_axis_raddr <= m_axis_raddr + 1'b1;
  end
end

always @(*)
begin
  if (read & ~write)
    level_next <= level - 1'b1;
  else if (~read & write)
    level_next <= level + 1'b1;
  else
    level_next <= level;
end

always @(posedge clk)
begin
  if (resetn == 1'b0) begin
    m_axis_valid <= 1'b0;
    s_axis_ready <= 1'b0;
    level <= 'h00;
    room <= MAX_ROOM;
    s_axis_empty <= 'h00;
  end else begin
    level <= level_next;
    room <= MAX_ROOM - level_next;
    m_axis_valid <= level_next != 0;
    s_axis_ready <= level_next != MAX_ROOM;
    s_axis_empty <= level_next == 0;
  end
end

endmodule
module fifo_address_gray #(
  parameter ADDRESS_WIDTH = 4
) (
  input m_axis_aclk,
  input m_axis_aresetn,
  input m_axis_ready,
  output reg m_axis_valid,
  output reg [ADDRESS_WIDTH:0] m_axis_level,

  input s_axis_aclk,
  input s_axis_aresetn,
  output reg s_axis_ready,
  input s_axis_valid,
  output reg s_axis_empty,
  output [ADDRESS_WIDTH-1:0] s_axis_waddr,
  output reg [ADDRESS_WIDTH:0] s_axis_room
);

reg [ADDRESS_WIDTH:0] _s_axis_waddr = 'h00;
reg [ADDRESS_WIDTH:0] _s_axis_waddr_next;

reg [ADDRESS_WIDTH:0] _m_axis_raddr = 'h00;
reg [ADDRESS_WIDTH:0] _m_axis_raddr_next;

reg [ADDRESS_WIDTH:0] s_axis_waddr_gray = 'h00;
wire [ADDRESS_WIDTH:0] s_axis_waddr_gray_next;
wire [ADDRESS_WIDTH:0] s_axis_raddr_gray;

reg [ADDRESS_WIDTH:0] m_axis_raddr_gray = 'h00;
wire [ADDRESS_WIDTH:0] m_axis_raddr_gray_next;
wire [ADDRESS_WIDTH:0] m_axis_waddr_gray;

assign s_axis_waddr = _s_axis_waddr[ADDRESS_WIDTH-1:0];

always @(*)
begin
  if (s_axis_ready && s_axis_valid)
    _s_axis_waddr_next <= _s_axis_waddr + 1;
  else
    _s_axis_waddr_next <= _s_axis_waddr;
end

assign s_axis_waddr_gray_next = _s_axis_waddr_next ^ _s_axis_waddr_next[ADDRESS_WIDTH:1];

always @(posedge s_axis_aclk)
begin
  if (s_axis_aresetn == 1'b0) begin
    _s_axis_waddr <= 'h00;
    s_axis_waddr_gray <= 'h00;
  end else begin
    _s_axis_waddr <= _s_axis_waddr_next;
    s_axis_waddr_gray <= s_axis_waddr_gray_next;
  end
end

always @(*)
begin
  if (m_axis_ready && m_axis_valid)
    _m_axis_raddr_next <= _m_axis_raddr + 1;
  else
    _m_axis_raddr_next <= _m_axis_raddr;
end

assign m_axis_raddr_gray_next = _m_axis_raddr_next ^ _m_axis_raddr_next[ADDRESS_WIDTH:1];

always @(posedge m_axis_aclk)
begin
  if (m_axis_aresetn == 1'b0) begin
    _m_axis_raddr <= 'h00;
    m_axis_raddr_gray <= 'h00;
  end else begin
    _m_axis_raddr <= _m_axis_raddr_next;
    m_axis_raddr_gray <= m_axis_raddr_gray_next;
  end
end

sync_bits #(
  .NUM_OF_BITS(ADDRESS_WIDTH + 1)
) i_waddr_sync (
  .out_clk(m_axis_aclk),
  .out_resetn(m_axis_aresetn),
  .in_bits(s_axis_waddr_gray),
  .out_bits(m_axis_waddr_gray)
);

sync_bits #(
  .NUM_OF_BITS(ADDRESS_WIDTH + 1)
) i_raddr_sync (
  .out_clk(s_axis_aclk),
  .out_resetn(s_axis_aresetn),
  .in_bits(m_axis_raddr_gray),
  .out_bits(s_axis_raddr_gray)
);

always @(posedge s_axis_aclk)
begin
  if (s_axis_aresetn == 1'b0) begin
    s_axis_ready <= 1'b1;
    s_axis_empty <= 1'b1;
  end else begin
    s_axis_ready <= (s_axis_raddr_gray[ADDRESS_WIDTH] == s_axis_waddr_gray_next[ADDRESS_WIDTH] ||
      s_axis_raddr_gray[ADDRESS_WIDTH-1] == s_axis_waddr_gray_next[ADDRESS_WIDTH-1] ||
      s_axis_raddr_gray[ADDRESS_WIDTH-2:0] != s_axis_waddr_gray_next[ADDRESS_WIDTH-2:0]);
    s_axis_empty <= s_axis_raddr_gray == s_axis_waddr_gray_next;
  end
end

always @(posedge m_axis_aclk)
begin
  if (s_axis_aresetn == 1'b0)
    m_axis_valid <= 1'b0;
  else begin
    m_axis_valid <= m_axis_waddr_gray != m_axis_raddr_gray_next;
  end
end

endmodule
module fifo_address_gray_pipelined #(
  parameter ADDRESS_WIDTH = 4
) (
  input m_axis_aclk,
  input m_axis_aresetn,
  input m_axis_ready,
  output reg m_axis_valid,
  output [ADDRESS_WIDTH-1:0] m_axis_raddr,
  output reg [ADDRESS_WIDTH:0] m_axis_level,

  input s_axis_aclk,
  input s_axis_aresetn,
  output reg s_axis_ready,
  input s_axis_valid,
  output reg s_axis_empty,
  output [ADDRESS_WIDTH-1:0] s_axis_waddr,
  output reg [ADDRESS_WIDTH:0] s_axis_room
);

localparam MAX_ROOM = {1'b1,{ADDRESS_WIDTH{1'b0}}};

reg [ADDRESS_WIDTH:0] _s_axis_waddr = 'h00;
reg [ADDRESS_WIDTH:0] _s_axis_waddr_next;
wire [ADDRESS_WIDTH:0] _s_axis_raddr;

reg [ADDRESS_WIDTH:0] _m_axis_raddr = 'h00;
reg [ADDRESS_WIDTH:0] _m_axis_raddr_next;
wire [ADDRESS_WIDTH:0] _m_axis_waddr;

assign s_axis_waddr = _s_axis_waddr[ADDRESS_WIDTH-1:0];
assign m_axis_raddr = _m_axis_raddr[ADDRESS_WIDTH-1:0];

always @(*)
begin
  if (s_axis_ready && s_axis_valid)
    _s_axis_waddr_next <= _s_axis_waddr + 1'b1;
  else
    _s_axis_waddr_next <= _s_axis_waddr;
end

always @(posedge s_axis_aclk)
begin
  if (s_axis_aresetn == 1'b0) begin
    _s_axis_waddr <= 'h00;
  end else begin
    _s_axis_waddr <= _s_axis_waddr_next;
  end
end

always @(*)
begin
  if (m_axis_ready && m_axis_valid)
    _m_axis_raddr_next <= _m_axis_raddr + 1'b1;
  else
    _m_axis_raddr_next <= _m_axis_raddr;
end

always @(posedge m_axis_aclk)
begin
  if (m_axis_aresetn == 1'b0) begin
    _m_axis_raddr <= 'h00;
  end else begin
    _m_axis_raddr <= _m_axis_raddr_next;
  end
end

sync_gray #(
  .DATA_WIDTH(ADDRESS_WIDTH + 1)
) i_waddr_sync (
  .in_clk(s_axis_aclk),
  .in_resetn(s_axis_aresetn),
  .out_clk(m_axis_aclk),
  .out_resetn(m_axis_aresetn),
  .in_count(_s_axis_waddr),
  .out_count(_m_axis_waddr)
);

sync_gray #(
  .DATA_WIDTH(ADDRESS_WIDTH + 1)
) i_raddr_sync (
  .in_clk(m_axis_aclk),
  .in_resetn(m_axis_aresetn),
  .out_clk(s_axis_aclk),
  .out_resetn(s_axis_aresetn),
  .in_count(_m_axis_raddr),
  .out_count(_s_axis_raddr)
);

always @(posedge s_axis_aclk)
begin
  if (s_axis_aresetn == 1'b0) begin
    s_axis_ready <= 1'b1;
    s_axis_empty <= 1'b1;
    s_axis_room <= MAX_ROOM;
  end else begin
    s_axis_ready <= (_s_axis_raddr[ADDRESS_WIDTH] == _s_axis_waddr_next[ADDRESS_WIDTH] ||
      _s_axis_raddr[ADDRESS_WIDTH-1:0] != _s_axis_waddr_next[ADDRESS_WIDTH-1:0]);
    s_axis_empty <= _s_axis_raddr == _s_axis_waddr_next;
    s_axis_room <= _s_axis_raddr - _s_axis_waddr_next + MAX_ROOM;
  end
end

always @(posedge m_axis_aclk)
begin
  if (m_axis_aresetn == 1'b0) begin
    m_axis_valid <= 1'b0;
    m_axis_level <= 'h00;
  end else begin
    m_axis_valid <= _m_axis_waddr != _m_axis_raddr_next;
    m_axis_level <= _m_axis_waddr - _m_axis_raddr_next;
  end
end

endmodule
module axi_ad9680 #(

  parameter ID = 0,
  parameter FPGA_TECHNOLOGY = 0,
  parameter FPGA_FAMILY = 0,
  parameter SPEED_GRADE = 0,
  parameter DEV_PACKAGE = 0) (

  // jesd interface
  // rx_clk is (line-rate/40)

  input                   rx_clk,
  input       [ 3:0]      rx_sof,
  input                   rx_valid,
  input       [127:0]     rx_data,
  output                  rx_ready,

  // dma interface

  output                  adc_clk,
  output                  adc_enable_0,
  output                  adc_valid_0,
  output      [63:0]      adc_data_0,
  output                  adc_enable_1,
  output                  adc_valid_1,
  output      [63:0]      adc_data_1,
  input                   adc_dovf,

  // axi interface

  input                   s_axi_aclk,
  input                   s_axi_aresetn,
  input                   s_axi_awvalid,
  input       [11:0]      s_axi_awaddr,
  input       [ 2:0]      s_axi_awprot,
  output                  s_axi_awready,
  input                   s_axi_wvalid,
  input       [31:0]      s_axi_wdata,
  input       [ 3:0]      s_axi_wstrb,
  output                  s_axi_wready,
  output                  s_axi_bvalid,
  output      [ 1:0]      s_axi_bresp,
  input                   s_axi_bready,
  input                   s_axi_arvalid,
  input       [11:0]      s_axi_araddr,
  input       [ 2:0]      s_axi_arprot,
  output                  s_axi_arready,
  output                  s_axi_rvalid,
  output      [ 1:0]      s_axi_rresp,
  output      [31:0]      s_axi_rdata,
  input                   s_axi_rready);

  assign adc_clk = rx_clk;

  ad_ip_jesd204_tpl_adc #(
    .ID (ID),
    .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY),
    .FPGA_FAMILY (FPGA_FAMILY),
    .SPEED_GRADE (SPEED_GRADE),
    .DEV_PACKAGE (DEV_PACKAGE),
    .NUM_LANES (4),
    .NUM_CHANNELS (2),
    .SAMPLES_PER_FRAME (1),
    .CONVERTER_RESOLUTION (14),
    .BITS_PER_SAMPLE (16),
    .OCTETS_PER_BEAT (4),
    .TWOS_COMPLEMENT (1)
  ) i_adc_jesd204 (
    .link_clk (rx_clk),

    .link_sof (rx_sof),
    .link_valid (rx_valid),
    .link_data (rx_data),
    .link_ready (rx_ready),

    .enable ({adc_enable_1,adc_enable_0}),
    .adc_valid ({adc_valid_1,adc_valid_0}),
    .adc_data ({adc_data_1,adc_data_0}),
    .adc_dovf (adc_dovf),

    .s_axi_aclk (s_axi_aclk),
    .s_axi_aresetn (s_axi_aresetn),
    .s_axi_awvalid (s_axi_awvalid),
    .s_axi_awready (s_axi_awready),
    .s_axi_awaddr (s_axi_awaddr),
    .s_axi_awprot (s_axi_awprot),
    .s_axi_wvalid (s_axi_wvalid),
    .s_axi_wready (s_axi_wready),
    .s_axi_wdata (s_axi_wdata),
    .s_axi_wstrb (s_axi_wstrb),
    .s_axi_bvalid (s_axi_bvalid),
    .s_axi_bready (s_axi_bready),
    .s_axi_bresp (s_axi_bresp),
    .s_axi_arvalid (s_axi_arvalid),
    .s_axi_arready (s_axi_arready),
    .s_axi_araddr (s_axi_araddr),
    .s_axi_arprot (s_axi_arprot),
    .s_axi_rvalid (s_axi_rvalid),
    .s_axi_rready (s_axi_rready),
    .s_axi_rresp (s_axi_rresp),
    .s_axi_rdata (s_axi_rdata)
  );

endmodule
module sync_bits #(

  // Number of bits to synchronize
  parameter NUM_OF_BITS = 1,
  // Whether input and output clocks are asynchronous, if 0 the synchronizer will
  // be bypassed and the output signal equals the input signal.
  parameter ASYNC_CLK = 1)(

  input [NUM_OF_BITS-1:0] in_bits,
  input out_resetn,
  input out_clk,
  output [NUM_OF_BITS-1:0] out_bits);

generate if (ASYNC_CLK == 1) begin
  reg [NUM_OF_BITS-1:0] cdc_sync_stage1 = 'h0;
  reg [NUM_OF_BITS-1:0] cdc_sync_stage2 = 'h0;

  always @(posedge out_clk)
  begin
    if (out_resetn == 1'b0) begin
      cdc_sync_stage1 <= 'b0;
      cdc_sync_stage2 <= 'b0;
    end else begin
      cdc_sync_stage1 <= in_bits;
      cdc_sync_stage2 <= cdc_sync_stage1;
    end
  end

  assign out_bits = cdc_sync_stage2;
end else begin
  assign out_bits = in_bits;
end endgenerate

endmodule
module sync_event #(
  parameter NUM_OF_EVENTS = 1,
  parameter ASYNC_CLK = 1
) (
  input in_clk,
  input [NUM_OF_EVENTS-1:0] in_event,
  input out_clk,
  output reg [NUM_OF_EVENTS-1:0] out_event
);

generate
if (ASYNC_CLK == 1) begin

wire out_toggle;
wire in_toggle;

reg out_toggle_d1 = 1'b0;
reg in_toggle_d1 = 1'b0;

sync_bits i_sync_out (
  .in_bits(in_toggle_d1),
  .out_clk(out_clk),
  .out_resetn(1'b1),
  .out_bits(out_toggle)
);

sync_bits i_sync_in (
  .in_bits(out_toggle_d1),
  .out_clk(in_clk),
  .out_resetn(1'b1),
  .out_bits(in_toggle)
);

wire in_ready = in_toggle == in_toggle_d1;
wire load_out = out_toggle ^ out_toggle_d1;

reg [NUM_OF_EVENTS-1:0] in_event_sticky = 'h00;
wire [NUM_OF_EVENTS-1:0] pending_events = in_event_sticky | in_event;
wire [NUM_OF_EVENTS-1:0] out_event_s;

always @(posedge in_clk) begin
  if (in_ready == 1'b1) begin
    in_event_sticky <= {NUM_OF_EVENTS{1'b0}};
    if (|pending_events == 1'b1) begin
      in_toggle_d1 <= ~in_toggle_d1;
    end
  end else begin
    in_event_sticky <= pending_events;
  end
end

if (NUM_OF_EVENTS > 1) begin
  reg [NUM_OF_EVENTS-1:0] cdc_hold = 'h00;

  always @(posedge in_clk) begin
    if (in_ready == 1'b1) begin
      cdc_hold <= pending_events;
    end
  end

  assign out_event_s = cdc_hold;
end else begin
  // When there is only one event, we know that it is set.
  assign out_event_s = 1'b1;
end

always @(posedge out_clk) begin
  if (load_out == 1'b1) begin
    out_event <= out_event_s;
  end else begin
    out_event <= {NUM_OF_EVENTS{1'b0}};
  end
  out_toggle_d1 <= out_toggle;
end

end else begin
  always @(*) begin
    out_event <= in_event;
  end
end
endgenerate

endmodule
module sync_gray #(

  // Bit-width of the counter
  parameter DATA_WIDTH = 1,
  // Whether the input and output clock are asynchronous, if set to 0 the
  // synchronizer will be bypassed and out_count will be in_count.
  parameter ASYNC_CLK = 1)(

  input in_clk,
  input in_resetn,
  input [DATA_WIDTH-1:0] in_count,
  input out_resetn,
  input out_clk,
  output [DATA_WIDTH-1:0] out_count);

generate if (ASYNC_CLK == 1) begin
  reg [DATA_WIDTH-1:0] cdc_sync_stage0 = 'h0;
  reg [DATA_WIDTH-1:0] cdc_sync_stage1 = 'h0;
  reg [DATA_WIDTH-1:0] cdc_sync_stage2 = 'h0;
  reg [DATA_WIDTH-1:0] out_count_m = 'h0;

  function [DATA_WIDTH-1:0] g2b;
    input [DATA_WIDTH-1:0] g;
    reg   [DATA_WIDTH-1:0] b;
    integer i;
    begin
      b[DATA_WIDTH-1] = g[DATA_WIDTH-1];
      for (i = DATA_WIDTH - 2; i >= 0; i =  i - 1)
        b[i] = b[i + 1] ^ g[i];
      g2b = b;
    end
  endfunction

  function [DATA_WIDTH-1:0] b2g;
    input [DATA_WIDTH-1:0] b;
    reg [DATA_WIDTH-1:0] g;
    integer i;
    begin
      g[DATA_WIDTH-1] = b[DATA_WIDTH-1];
      for (i = DATA_WIDTH - 2; i >= 0; i = i -1)
          g[i] = b[i + 1] ^ b[i];
      b2g = g;
    end
  endfunction

  always @(posedge in_clk) begin
    if (in_resetn == 1'b0) begin
      cdc_sync_stage0 <= 'h00;
    end else begin
      cdc_sync_stage0 <= b2g(in_count);
    end
  end

  always @(posedge out_clk) begin
    if (out_resetn == 1'b0) begin
      cdc_sync_stage1 <= 'h00;
      cdc_sync_stage2 <= 'h00;
      out_count_m <= 'h00;
    end else begin
      cdc_sync_stage1 <= cdc_sync_stage0;
      cdc_sync_stage2 <= cdc_sync_stage1;
      out_count_m <= g2b(cdc_sync_stage2);
    end
  end

  assign out_count = out_count_m;
end else begin
  assign out_count = in_count;
end endgenerate

endmodule
module sync_data #(
  parameter NUM_OF_BITS = 1,
  parameter ASYNC_CLK = 1
) (
  input in_clk,
  input [NUM_OF_BITS-1:0] in_data,
  input out_clk,
  output reg [NUM_OF_BITS-1:0] out_data
);

generate
if (ASYNC_CLK == 1) begin

wire out_toggle;
wire in_toggle;

reg out_toggle_d1 = 1'b0;
reg in_toggle_d1 = 1'b0;

reg [NUM_OF_BITS-1:0] cdc_hold;

sync_bits i_sync_out (
  .in_bits(in_toggle_d1),
  .out_clk(out_clk),
  .out_resetn(1'b1),
  .out_bits(out_toggle)
);

sync_bits i_sync_in (
  .in_bits(out_toggle_d1),
  .out_clk(in_clk),
  .out_resetn(1'b1),
  .out_bits(in_toggle)
);

wire in_load = in_toggle == in_toggle_d1;
wire out_load = out_toggle ^ out_toggle_d1;

always @(posedge in_clk) begin
  if (in_load == 1'b1) begin
    cdc_hold <= in_data;
    in_toggle_d1 <= ~in_toggle_d1;
  end
end

always @(posedge out_clk) begin
  if (out_load == 1'b1) begin
    out_data <= cdc_hold;
  end
  out_toggle_d1 <= out_toggle;
end

end else begin
  always @(*) begin
    out_data <= in_data;
  end
end
endgenerate

endmodule
module axi_ad9671_channel #(

  parameter CHANNEL_ID = 0) (

  // adc interface

  input                   adc_clk,
  input                   adc_rst,
  input                   adc_valid,
  input       [15:0]      adc_data,
  input                   adc_or,

  // channel interface

  output                  adc_dfmt_valid,
  output      [15:0]      adc_dfmt_data,
  output                  adc_enable,
  output                  up_adc_pn_err,
  output                  up_adc_pn_oos,
  output                  up_adc_or,

  // processor interface

  input                   up_rstn,
  input                   up_clk,
  input                   up_wreq,
  input       [13:0]      up_waddr,
  input       [31:0]      up_wdata,
  output                  up_wack,
  input                   up_rreq,
  input       [13:0]      up_raddr,
  output      [31:0]      up_rdata,
  output                  up_rack);


  // internal signals

  wire            adc_dfmt_se_s;
  wire            adc_dfmt_type_s;
  wire            adc_dfmt_enable_s;
  wire    [ 3:0]  adc_pnseq_sel_s;
  wire            adc_pn_err_s;
  wire            adc_pn_oos_s;

  // instantiations

  axi_ad9671_pnmon i_pnmon (
    .adc_clk (adc_clk),
    .adc_valid (adc_valid),
    .adc_data (adc_data),
    .adc_pn_oos (adc_pn_oos_s),
    .adc_pn_err (adc_pn_err_s),
    .adc_pnseq_sel (adc_pnseq_sel_s));

  ad_datafmt #(.DATA_WIDTH(16)) i_ad_datafmt (
    .clk (adc_clk),
    .valid (adc_valid),
    .data (adc_data),
    .valid_out (adc_dfmt_valid),
    .data_out (adc_dfmt_data),
    .dfmt_enable (adc_dfmt_enable_s),
    .dfmt_type (adc_dfmt_type_s),
    .dfmt_se (adc_dfmt_se_s));

  up_adc_channel #(.CHANNEL_ID(CHANNEL_ID)) i_up_adc_channel (
    .adc_clk (adc_clk),
    .adc_rst (adc_rst),
    .adc_enable (adc_enable),
    .adc_iqcor_enb (),
    .adc_dcfilt_enb (),
    .adc_dfmt_se (adc_dfmt_se_s),
    .adc_dfmt_type (adc_dfmt_type_s),
    .adc_dfmt_enable (adc_dfmt_enable_s),
    .adc_dcfilt_offset (),
    .adc_dcfilt_coeff (),
    .adc_iqcor_coeff_1 (),
    .adc_iqcor_coeff_2 (),
    .adc_pnseq_sel (adc_pnseq_sel_s),
    .adc_data_sel (),
    .adc_pn_err (adc_pn_err_s),
    .adc_pn_oos (adc_pn_oos_s),
    .adc_or (adc_or),
    .up_adc_pn_err (up_adc_pn_err),
    .up_adc_pn_oos (up_adc_pn_oos),
    .up_adc_or (up_adc_or),
    .up_usr_datatype_be (),
    .up_usr_datatype_signed (),
    .up_usr_datatype_shift (),
    .up_usr_datatype_total_bits (),
    .up_usr_datatype_bits (),
    .up_usr_decimation_m (),
    .up_usr_decimation_n (),
    .adc_usr_datatype_be (1'b0),
    .adc_usr_datatype_signed (1'b1),
    .adc_usr_datatype_shift (8'd0),
    .adc_usr_datatype_total_bits (8'd16),
    .adc_usr_datatype_bits (8'd16),
    .adc_usr_decimation_m (16'd1),
    .adc_usr_decimation_n (16'd1),
    .up_rstn (up_rstn),
    .up_clk (up_clk),
    .up_wreq (up_wreq),
    .up_waddr (up_waddr),
    .up_wdata (up_wdata),
    .up_wack (up_wack),
    .up_rreq (up_rreq),
    .up_raddr (up_raddr),
    .up_rdata (up_rdata),
    .up_rack (up_rack));

endmodule
module spi_engine_interconnect #(

  parameter DATA_WIDTH = 8,                   // Valid data widths values are 8/16/24/32
  parameter NUM_OF_SDI = 1 ) (

  input clk,
  input resetn,

  output m_cmd_valid,
  input m_cmd_ready,
  output [15:0] m_cmd_data,

  output m_sdo_valid,
  input m_sdo_ready,
  output [(DATA_WIDTH-1):0] m_sdo_data,

  input m_sdi_valid,
  output m_sdi_ready,
  input [(NUM_OF_SDI * DATA_WIDTH-1):0] m_sdi_data,

  input m_sync_valid,
  output m_sync_ready,
  input [7:0] m_sync,


  input s0_cmd_valid,
  output s0_cmd_ready,
  input [15:0] s0_cmd_data,

  input s0_sdo_valid,
  output s0_sdo_ready,
  input [(DATA_WIDTH-1):0] s0_sdo_data,

  output s0_sdi_valid,
  input s0_sdi_ready,
  output [(NUM_OF_SDI * DATA_WIDTH-1):0] s0_sdi_data,

  output s0_sync_valid,
  input s0_sync_ready,
  output [7:0] s0_sync,


  input s1_cmd_valid,
  output s1_cmd_ready,
  input [15:0] s1_cmd_data,

  input s1_sdo_valid,
  output s1_sdo_ready,
  input [(DATA_WIDTH-1):0] s1_sdo_data,

  output s1_sdi_valid,
  input s1_sdi_ready,
  output [(NUM_OF_SDI * DATA_WIDTH-1):0] s1_sdi_data,

  output s1_sync_valid,
  input s1_sync_ready,
  output [7:0] s1_sync
);

reg s_active = 1'b0;

reg idle = 1'b1;

`define spi_engine_interconnect_mux(s0, s1) (idle == 1'b1 ? 1'b0 : (s_active == 1'b0 ? s0 : s1))

assign m_cmd_data   = s_active == 1'b0 ? s0_cmd_data : s1_cmd_data;
assign m_cmd_valid  = `spi_engine_interconnect_mux(s0_cmd_valid, s1_cmd_valid);
assign s0_cmd_ready = `spi_engine_interconnect_mux(m_cmd_ready, 1'b0);
assign s1_cmd_ready = `spi_engine_interconnect_mux(1'b0, m_cmd_ready);

assign m_sdo_data   = s_active == 1'b0 ? s0_sdo_data : s1_sdo_data;
assign m_sdo_valid  = `spi_engine_interconnect_mux(s0_sdo_valid, s1_sdo_valid);
assign s0_sdo_ready = `spi_engine_interconnect_mux(m_sdo_ready, 1'b0);
assign s1_sdo_ready = `spi_engine_interconnect_mux(1'b0, m_sdo_ready);

assign s0_sdi_data  = m_sdi_data;
assign s1_sdi_data  = m_sdi_data;
assign m_sdi_ready  = `spi_engine_interconnect_mux(s0_sdi_ready, s1_sdi_ready);
assign s0_sdi_valid = `spi_engine_interconnect_mux(m_sdi_valid, 1'b0);
assign s1_sdi_valid = `spi_engine_interconnect_mux(1'b0, m_sdi_valid);

assign s0_sync       = m_sync;
assign s1_sync       = m_sync;
assign m_sync_ready  = `spi_engine_interconnect_mux(s0_sync_ready, s1_sync_ready);
assign s0_sync_valid = `spi_engine_interconnect_mux(m_sync_valid, 1'b0);
assign s1_sync_valid = `spi_engine_interconnect_mux(1'b0, m_sync_valid);

always @(posedge clk) begin
  if (idle == 1'b1) begin
    if (s0_cmd_valid)
      s_active <= 1'b0;
    else if (s1_cmd_valid)
      s_active <= 1'b1;
  end
end

always @(posedge clk) begin
  if (resetn == 1'b0) begin
    idle <= 1'b1;
  end else begin
    if (m_sync_valid == 1'b1 && m_sync_ready == 1'b1) begin
      idle <= 1'b1;
    end else if (s0_cmd_valid == 1'b1 || s1_cmd_valid == 1'b1) begin
      idle <= 1'b0;
    end
  end
end

endmodule
module util_cpack2_impl #(
  parameter NUM_OF_CHANNELS = 4,
  parameter SAMPLES_PER_CHANNEL = 1,
  parameter SAMPLE_DATA_WIDTH = 16
) (
  input clk,
  input reset,

  input [NUM_OF_CHANNELS-1:0] enable,

  input [NUM_OF_CHANNELS-1:0] fifo_wr_en,
  output fifo_wr_overflow,
  input [NUM_OF_CHANNELS*SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_wr_data,

  output reg packed_fifo_wr_en = 1'b0,
  input packed_fifo_wr_overflow,
  output reg packed_fifo_wr_sync = 1'b1,
  output reg [NUM_OF_CHANNELS*SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] packed_fifo_wr_data = 'h00
);
  localparam TOTAL_DATA_WIDTH = SAMPLE_DATA_WIDTH * SAMPLES_PER_CHANNEL * NUM_OF_CHANNELS;

  /*
   * Control signals from the pack shell.
   */
  wire reset_data;
  wire ready;

  /*
   * Interleaved version of `fifo_wr_data`.
   */
  wire [TOTAL_DATA_WIDTH-1:0] interleaved_data;

  /*
   * Output data and corresponding control signal from the routing network.
   */
  wire [TOTAL_DATA_WIDTH-1:0] out_data;
  wire out_sync;
  wire [NUM_OF_CHANNELS*SAMPLES_PER_CHANNEL-1:0] out_valid;

  /*
   * Only the first signal of fifo_rd_en is used. All others are ignored. The
   * only reason why fifo_rd_en has multiple entries is to keep the interface
   * somewhat backwards compatible to the previous upack.
   */
  wire data_wr_en = fifo_wr_en[0];

  /*
   * The cpack core itself has no backpressure. Overflows can only happen
   * downstream.
   */

  assign fifo_wr_overflow = packed_fifo_wr_overflow;

  /*
   * Data at the input of the routing network should be interleaved. The cpack
   * core is supposed to accept deinterleaved data. This just rearrange the bits
   * in the data vector and does not consume any FPGA resources.
   */
  ad_perfect_shuffle #(
    .NUM_GROUPS (NUM_OF_CHANNELS),
    .WORDS_PER_GROUP (SAMPLES_PER_CHANNEL),
    .WORD_WIDTH (SAMPLE_DATA_WIDTH)
  ) i_interleave (
    .data_in (fifo_wr_data),
    .data_out (interleaved_data)
  );

  pack_shell #(
    .NUM_OF_CHANNELS (NUM_OF_CHANNELS),
    .SAMPLES_PER_CHANNEL (SAMPLES_PER_CHANNEL),
    .SAMPLE_DATA_WIDTH (SAMPLE_DATA_WIDTH),
    .PACK (1)
  ) i_pack_shell (
    .clk (clk),
    .reset (reset),

    .reset_data (reset_data),

    .enable (enable),
    .ce (data_wr_en),
    .ready (ready),
    .in_data (interleaved_data),
    .out_data (out_data),
    .out_sync (out_sync),
    .out_valid (out_valid)
  );

  always @(posedge clk) begin
    if (reset_data == 1'b1) begin
      packed_fifo_wr_en <= 1'b0;
      packed_fifo_wr_sync <= 1'b0;
    end else if (ready == 1'b1 && data_wr_en == 1'b1) begin
      packed_fifo_wr_en <= 1'b1;
      packed_fifo_wr_sync <= out_sync;
    end else begin
      packed_fifo_wr_en <= 1'b0;
      packed_fifo_wr_sync <= 1'b0;
    end
  end


  always @(posedge clk) begin: gen_packed_fifo_wr_data
    integer i;

    if (data_wr_en == 1'b1) begin
      for (i = 0; i < NUM_OF_CHANNELS * SAMPLES_PER_CHANNEL; i = i + 1) begin
        if (out_valid[i] == 1'b1) begin
          packed_fifo_wr_data[i*SAMPLE_DATA_WIDTH+:SAMPLE_DATA_WIDTH] <= out_data[i*SAMPLE_DATA_WIDTH+:SAMPLE_DATA_WIDTH];
        end
      end
    end
  end

endmodule
module util_upack2_impl #(
  parameter NUM_OF_CHANNELS = 4,
  parameter SAMPLES_PER_CHANNEL = 1,
  parameter SAMPLE_DATA_WIDTH = 16
) (
  input clk,
  input reset,

  input [NUM_OF_CHANNELS-1:0] enable,

  input [NUM_OF_CHANNELS-1:0] fifo_rd_en,
  output reg fifo_rd_valid,
  output reg fifo_rd_underflow,
  output reg [NUM_OF_CHANNELS*SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data,

  input s_axis_valid,
  output s_axis_ready,
  input [NUM_OF_CHANNELS*SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] s_axis_data
);

  /*
   * Final output data of the routing network that will be written to
   * `fifo_rd_data` after being deinterleaved.
   */
  wire [NUM_OF_CHANNELS*SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] out_data;

  /*
   * Deinterleaved version of `out_data`
   */
  wire [NUM_OF_CHANNELS*SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] deinterleaved_data;

  /*
   * Internal read signal.
   */
  wire data_rd_en;

  /*
   * Control signals from/to the pack shell.
   */
  wire ce;
  wire ready;
  wire reset_data;

  /*
   * Only the first signal of fifo_rd_en is used. All others are ignored. The
   * only reason why fifo_rd_en has multiple entries is to keep the interface
   * somewhat backwards compatible to the previous upack.
   */
  assign data_rd_en = fifo_rd_en[0];

  assign ce = s_axis_valid & data_rd_en;
  assign s_axis_ready = ready & ce;

  pack_shell #(
    .NUM_OF_CHANNELS (NUM_OF_CHANNELS),
    .SAMPLES_PER_CHANNEL (SAMPLES_PER_CHANNEL),
    .SAMPLE_DATA_WIDTH (SAMPLE_DATA_WIDTH),
    .PACK (0)
  ) i_pack_shell (
    .clk (clk),
    .reset (reset),

    .reset_data (reset_data),

    .enable (enable),
    .ce (ce),
    .ready (ready),
    .in_data (s_axis_data),
    .out_data (out_data),

    .out_valid (),
    .out_sync ()
  );

  /*
   * Data at the output of the routing network is interleaved. The upack
   * core is supposed to produce deinterleaved data. This just rearrange the
   * bits in the data vector and does not consume any FPGA resources.
   */
  ad_perfect_shuffle #(
    .NUM_GROUPS (SAMPLES_PER_CHANNEL),
    .WORDS_PER_GROUP (NUM_OF_CHANNELS),
    .WORD_WIDTH (SAMPLE_DATA_WIDTH)
  ) i_deinterleave (
    .data_in (out_data),
    .data_out (deinterleaved_data)
  );

  always @(posedge clk) begin
    /* In case of an underflow the output vector should be zeroed */
    if (reset_data == 1'b1 ||
        (data_rd_en == 1'b1 && s_axis_valid == 1'b0)) begin
      fifo_rd_data <= 'h00;
    end else if (data_rd_en == 1'b1) begin
      fifo_rd_data <= deinterleaved_data;
    end
  end

  always @(posedge clk) begin
    if (data_rd_en == 1'b1) begin
      fifo_rd_valid <= s_axis_valid & ~reset_data;
      fifo_rd_underflow <= ~(s_axis_valid & ~reset_data);
    end else begin
      fifo_rd_valid <= 1'b0;
      fifo_rd_underflow <= 1'b0;
    end
  end

endmodule