dakies/OSS_Verilog huggingface dataset:
module dmac_dest_fifo_inf #(

  parameter ID_WIDTH = 3,
  parameter DATA_WIDTH = 64,
  parameter BEATS_PER_BURST_WIDTH = 4)(

  input clk,
  input resetn,

  input enable,
  output enabled,

  input req_valid,
  output req_ready,

  output [ID_WIDTH-1:0] response_id,
  output reg [ID_WIDTH-1:0] data_id = 'h0,
  input data_eot,
  input response_eot,

  input en,
  output reg [DATA_WIDTH-1:0] dout,
  output reg valid,
  output reg underflow,

  output xfer_req,

  output fifo_ready,
  input fifo_valid,
  input [DATA_WIDTH-1:0] fifo_data,
  input fifo_last,

  output response_valid,
  input response_ready,
  output response_resp_eot,
  output [1:0] response_resp
);

`include "inc_id.vh"

reg active = 1'b0;

/* Last beat of the burst */
wire fifo_last_beat;
/* Last beat of the segment */
wire fifo_eot_beat;

assign enabled = enable;
assign fifo_ready = en & (fifo_valid | ~enable);

/* fifo_last == 1'b1 implies fifo_valid == 1'b1 */
assign fifo_last_beat = fifo_ready & fifo_last;
assign fifo_eot_beat = fifo_last_beat & data_eot;

assign req_ready = fifo_eot_beat | ~active;
assign xfer_req = active;

always @(posedge clk) begin
  if (en) begin
    dout <= fifo_valid ? fifo_data : {DATA_WIDTH{1'b0}};
    valid <= fifo_valid & enable;
    underflow <= ~(fifo_valid & enable);
  end else begin
    valid <= 1'b0;
    underflow <= 1'b0;
  end
end

always @(posedge clk) begin
  if (resetn == 1'b0) begin
    data_id <= 'h00;
  end else if (fifo_last_beat == 1'b1) begin
    data_id <= inc_id(data_id);
  end
end

always @(posedge clk) begin
  if (resetn == 1'b0) begin
    active <= 1'b0;
  end else if (req_valid == 1'b1) begin
    active <= 1'b1;
  end else if (fifo_eot_beat == 1'b1) begin
    active <= 1'b0;
  end
end

dmac_response_generator # (
  .ID_WIDTH(ID_WIDTH)
) i_response_generator (
  .clk(clk),
  .resetn(resetn),

  .enable(enable),
  .enabled(),

  .request_id(data_id),
  .response_id(response_id),

  .eot(response_eot),

  .resp_valid(response_valid),
  .resp_ready(response_ready),
  .resp_eot(response_resp_eot),
  .resp_resp(response_resp)
);

endmodule
module dmac_response_handler #(

  parameter ID_WIDTH = 3)(

  input clk,
  input resetn,

  input bvalid,
  output bready,
  input [1:0] bresp,

  output reg [ID_WIDTH-1:0] id,
  input [ID_WIDTH-1:0] request_id,

  input enable,
  output reg enabled,

  input eot,

  output resp_valid,
  input resp_ready,
  output resp_eot,
  output [1:0] resp_resp
);

`include "resp.vh"
`include "inc_id.vh"

assign resp_resp = bresp;
assign resp_eot = eot;

wire active = id != request_id;

assign bready = active && resp_ready;
assign resp_valid = active && bvalid;

// We have to wait for all responses before we can disable the response handler
always @(posedge clk) begin
  if (resetn == 1'b0) begin
    enabled <= 1'b0;
  end else if (enable == 1'b1) begin
      enabled <= 1'b1;
  end else if (request_id == id) begin
      enabled <= 1'b0;
  end
end

always @(posedge clk) begin
  if (resetn == 1'b0) begin
    id <= 'h0;
  end else if (bready == 1'b1 && bvalid == 1'b1) begin
    id <= inc_id(id);
  end
end

endmodule
module dmac_response_generator #(

  parameter ID_WIDTH = 3)(

  input clk,
  input resetn,

  input enable,
  output reg enabled,

  input [ID_WIDTH-1:0] request_id,
  output reg [ID_WIDTH-1:0] response_id,

  input eot,

  output resp_valid,
  input resp_ready,
  output resp_eot,
  output [1:0] resp_resp
);

`include "inc_id.vh"
`include "resp.vh"

assign resp_resp = RESP_OKAY;
assign resp_eot = eot;

assign resp_valid = request_id != response_id && enabled;

// We have to wait for all responses before we can disable the response handler
always @(posedge clk) begin
  if (resetn == 1'b0) begin
    enabled <= 1'b0;
  end else if (enable == 1'b1) begin
    enabled <= 1'b1;
  end else if (request_id == response_id) begin
    enabled <= 1'b0;
  end
end

always @(posedge clk) begin
  if (resetn == 1'b0) begin
    response_id <= 'h0;
  end else if (resp_valid == 1'b1 && resp_ready == 1'b1) begin
    response_id <= inc_id(response_id);
  end
end

endmodule
module axi_dmac_resize_src #(
  parameter DATA_WIDTH_SRC = 64,
  parameter BYTES_PER_BEAT_WIDTH_SRC = 3,
  parameter DATA_WIDTH_MEM = 64,
  parameter BYTES_PER_BEAT_WIDTH_MEM = 3
) (
  input clk,
  input reset,

  input src_data_valid,
  input [DATA_WIDTH_SRC-1:0] src_data,
  input src_data_last,
  input [BYTES_PER_BEAT_WIDTH_SRC-1:0] src_data_valid_bytes,
  input src_data_partial_burst,

  output mem_data_valid,
  output [DATA_WIDTH_MEM-1:0] mem_data,
  output mem_data_last,
  output [BYTES_PER_BEAT_WIDTH_MEM-1:0] mem_data_valid_bytes,
  output mem_data_partial_burst
);

generate if (DATA_WIDTH_SRC == DATA_WIDTH_MEM)  begin
  assign mem_data_valid = src_data_valid;
  assign mem_data = src_data;
  assign mem_data_last = src_data_last;
  assign mem_data_valid_bytes = src_data_valid_bytes;
  assign mem_data_partial_burst = src_data_partial_burst;
end else begin

  localparam RATIO = DATA_WIDTH_MEM / DATA_WIDTH_SRC;
  localparam RATIO_WIDTH = RATIO > 64 ? 7 :
                           RATIO > 32 ? 6 :
                           RATIO > 16 ? 5 :
                           RATIO > 8 ? 4 :
                           RATIO > 4 ? 3 :
                           RATIO > 2 ? 2 : 1;

  reg [RATIO-1:0] mask = 'h1;
  reg valid = 1'b0;
  reg last = 1'b0;
  reg [DATA_WIDTH_MEM-1:0] data = 'h0;
  reg [BYTES_PER_BEAT_WIDTH_SRC-1:0] valid_bytes = 'h00;
  reg partial_burst = 1'b0;
  reg [RATIO_WIDTH-1:0] num_beats = {RATIO_WIDTH{1'b1}};

  always @(posedge clk) begin
    if (reset == 1'b1) begin
      valid <= 1'b0;
      mask <= 'h1;
    end else if (src_data_valid == 1'b1) begin
      valid <= mask[RATIO-1] || src_data_last;
      if (src_data_last) begin
        mask <= 'h1;
      end else begin
        mask <= {mask[RATIO-2:0],mask[RATIO-1]};
      end
    end else begin
      valid <= 1'b0;
    end
  end

  // This counter will hold the number of source beat in a destination beat
  // minus one
  always @(posedge clk) begin
    if (reset == 1'b1) begin
      num_beats <= {RATIO_WIDTH{1'b1}};
    end else if (valid == 1'b1 && last == 1'b1) begin
      if (src_data_valid == 1'b1) begin
        num_beats <= {RATIO_WIDTH{1'b0}};
      end else begin
        num_beats <= {RATIO_WIDTH{1'b1}};
      end
    end else if (src_data_valid == 1'b1) begin
      num_beats <= num_beats + 1'b1;
    end
  end

  integer i;

  always @(posedge clk) begin
    for (i = 0; i < RATIO; i = i+1) begin
      if (mask[i] == 1'b1) begin
        data[i*DATA_WIDTH_SRC+:DATA_WIDTH_SRC] <= src_data;
      end
    end

    // Compensate for the one clock cycle pipeline delay of the data
    last <= src_data_last;
    if (src_data_valid == 1'b1) begin
      valid_bytes <= src_data_valid_bytes;
      partial_burst <= src_data_partial_burst;
    end
  end

  assign mem_data_valid = valid;
  assign mem_data = data;
  assign mem_data_last = last;
  assign mem_data_valid_bytes = {num_beats,valid_bytes};
  assign mem_data_partial_burst = partial_burst;

end endgenerate

endmodule
module dmac_dest_axi_stream #(

  parameter ID_WIDTH = 3,
  parameter S_AXIS_DATA_WIDTH = 64,
  parameter BEATS_PER_BURST_WIDTH = 4)(

  input s_axis_aclk,
  input s_axis_aresetn,

  input enable,
  output enabled,
  output xfer_req,

  output [ID_WIDTH-1:0] response_id,
  output [ID_WIDTH-1:0] data_id,
  input data_eot,
  input response_eot,

  input m_axis_ready,
  output m_axis_valid,
  output [S_AXIS_DATA_WIDTH-1:0] m_axis_data,
  output m_axis_last,

  output fifo_ready,
  input fifo_valid,
  input [S_AXIS_DATA_WIDTH-1:0] fifo_data,
  input fifo_last,

  input req_valid,
  output req_ready,
  input req_xlast,

  output response_valid,
  input response_ready,
  output response_resp_eot,
  output [1:0] response_resp
);

`include "inc_id.vh"

reg data_enabled = 1'b0;
reg req_xlast_d = 1'b0;
reg active = 1'b0;

reg [ID_WIDTH-1:0] id = 'h0;

/* Last beat of the burst */
wire fifo_last_beat;
/* Last beat of the segment */
wire fifo_eot_beat;

/* fifo_last == 1'b1 implies fifo_valid == 1'b1 */
assign fifo_last_beat = fifo_ready & fifo_last;
assign fifo_eot_beat = fifo_last_beat & data_eot;

assign req_ready = fifo_eot_beat | ~active;
assign data_id = id;
assign xfer_req = active;

assign m_axis_valid = fifo_valid & active;
assign fifo_ready = m_axis_ready & active;
assign m_axis_last = req_xlast_d & fifo_last & data_eot;
assign m_axis_data = fifo_data;

always @(posedge s_axis_aclk) begin
  if (s_axis_aresetn == 1'b0) begin
    data_enabled <= 1'b0;
  end else if (enable == 1'b1) begin
    data_enabled <= 1'b1;
  end else if (m_axis_valid == 1'b0 || m_axis_ready == 1'b1) begin
    data_enabled <= 1'b0;
  end
end

always @(posedge s_axis_aclk) begin
  if (req_ready == 1'b1) begin
    req_xlast_d <= req_xlast;
  end
end

always @(posedge s_axis_aclk) begin
  if (s_axis_aresetn == 1'b0) begin
    active <= 1'b0;
  end else if (req_valid == 1'b1) begin
    active <= 1'b1;
  end else if (fifo_eot_beat == 1'b1) begin
    active <= 1'b0;
  end
end

always @(posedge s_axis_aclk) begin
  if (s_axis_aresetn == 1'b0) begin
    id <= 'h00;
  end else if (fifo_last_beat == 1'b1) begin
    id <= inc_id(id);
  end
end

dmac_response_generator # (
  .ID_WIDTH(ID_WIDTH)
) i_response_generator (
  .clk(s_axis_aclk),
  .resetn(s_axis_aresetn),

  .enable(data_enabled),
  .enabled(enabled),

  .request_id(id),
  .response_id(response_id),

  .eot(response_eot),

  .resp_valid(response_valid),
  .resp_ready(response_ready),
  .resp_eot(response_resp_eot),
  .resp_resp(response_resp)
);

endmodule
module dmac_src_axi_stream #(

  parameter ID_WIDTH = 3,
  parameter S_AXIS_DATA_WIDTH = 64,
  parameter LENGTH_WIDTH = 24,
  parameter BEATS_PER_BURST_WIDTH = 4)(

  input s_axis_aclk,
  input s_axis_aresetn,

  input enable,
  output enabled,

  input [ID_WIDTH-1:0] request_id,
  output [ID_WIDTH-1:0] response_id,
  input eot,

  output rewind_req_valid,
  input rewind_req_ready,
  output [ID_WIDTH+3-1:0] rewind_req_data,

  output                             bl_valid,
  input                              bl_ready,
  output [BEATS_PER_BURST_WIDTH-1:0] measured_last_burst_length,

  output block_descr_to_dst,

  output [ID_WIDTH-1:0] source_id,
  output source_eot,

  output s_axis_ready,
  input s_axis_valid,
  input [S_AXIS_DATA_WIDTH-1:0] s_axis_data,
  input [0:0] s_axis_user,
  input s_axis_last,
  output s_axis_xfer_req,

  output fifo_valid,
  output [S_AXIS_DATA_WIDTH-1:0] fifo_data,
  output fifo_last,
  output fifo_partial_burst,

  input req_valid,
  output req_ready,
  input [BEATS_PER_BURST_WIDTH-1:0] req_last_burst_length,
  input req_sync_transfer_start,
  input req_xlast
);

assign enabled = enable;

dmac_data_mover # (
  .ID_WIDTH(ID_WIDTH),
  .DATA_WIDTH(S_AXIS_DATA_WIDTH),
  .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH),
  .ALLOW_ABORT(1)
) i_data_mover (
  .clk(s_axis_aclk),
  .resetn(s_axis_aresetn),

  .xfer_req(s_axis_xfer_req),

  .request_id(request_id),
  .response_id(response_id),
  .eot(eot),

  .rewind_req_valid(rewind_req_valid),
  .rewind_req_ready(rewind_req_ready),
  .rewind_req_data(rewind_req_data),

  .bl_valid(bl_valid),
  .bl_ready(bl_ready),
  .measured_last_burst_length(measured_last_burst_length),

  .block_descr_to_dst(block_descr_to_dst),

  .source_id(source_id),
  .source_eot(source_eot),

  .req_valid(req_valid),
  .req_ready(req_ready),
  .req_last_burst_length(req_last_burst_length),
  .req_sync_transfer_start(req_sync_transfer_start),
  .req_xlast(req_xlast),

  .s_axi_valid(s_axis_valid),
  .s_axi_ready(s_axis_ready),
  .s_axi_data(s_axis_data),
  .s_axi_last(s_axis_last),
  .s_axi_sync(s_axis_user[0]),

  .m_axi_valid(fifo_valid),
  .m_axi_data(fifo_data),
  .m_axi_last(fifo_last),
  .m_axi_partial_burst(fifo_partial_burst)
);

endmodule
module dmac_src_fifo_inf #(

  parameter ID_WIDTH = 3,
  parameter DATA_WIDTH = 64,
  parameter BEATS_PER_BURST_WIDTH = 4)(

  input clk,
  input resetn,

  input enable,
  output enabled,

  input [ID_WIDTH-1:0] request_id,
  output [ID_WIDTH-1:0] response_id,
  input eot,

  output bl_valid,
  input bl_ready,
  output [BEATS_PER_BURST_WIDTH-1:0] measured_last_burst_length,

  input en,
  input [DATA_WIDTH-1:0] din,
  output reg overflow,
  input sync,
  output xfer_req,

  output fifo_valid,
  output [DATA_WIDTH-1:0] fifo_data,
  output fifo_last,

  input req_valid,
  output req_ready,
  input [BEATS_PER_BURST_WIDTH-1:0] req_last_burst_length,
  input req_sync_transfer_start
);

wire ready;
wire valid;

assign enabled = enable;

assign valid = en & ready;

always @(posedge clk)
begin
  if (enable) begin
    overflow <= en & ~ready;
  end else begin
    overflow <= en;
  end
end

dmac_data_mover # (
  .ID_WIDTH(ID_WIDTH),
  .DATA_WIDTH(DATA_WIDTH),
  .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH)
) i_data_mover (
  .clk(clk),
  .resetn(resetn),

  .xfer_req(xfer_req),

  .request_id(request_id),
  .response_id(response_id),
  .eot(eot),

  .bl_valid(bl_valid),
  .bl_ready(bl_ready),
  .measured_last_burst_length(measured_last_burst_length),

  .req_valid(req_valid),
  .req_ready(req_ready),
  .req_last_burst_length(req_last_burst_length),
  .req_sync_transfer_start(req_sync_transfer_start),
  .req_xlast(1'b0),

  .s_axi_ready(ready),
  .s_axi_valid(valid),
  .s_axi_data(din),
  .s_axi_sync(sync),
  .s_axi_last(1'b0),

  .m_axi_valid(fifo_valid),
  .m_axi_data(fifo_data),
  .m_axi_last(fifo_last)
);

endmodule
module splitter #(

  parameter NUM_M = 2)(

  input clk,
  input resetn,

  input s_valid,
  output s_ready,

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

reg [NUM_M-1:0] acked;

assign s_ready = &(m_ready | acked);
assign m_valid = s_valid ? ~acked : {NUM_M{1'b0}};

always @(posedge clk)
begin
  if (resetn == 1'b0) begin
    acked <= {NUM_M{1'b0}};
  end else begin
    if (s_valid & s_ready)
      acked <= {NUM_M{1'b0}};
    else
      acked <= acked | (m_ready & m_valid);
  end
end

endmodule
module axi_dmac_resize_dest #(
  parameter DATA_WIDTH_DEST = 64,
  parameter DATA_WIDTH_MEM = 64
) (
  input clk,
  input reset,

  input mem_data_valid,
  output mem_data_ready,
  input [DATA_WIDTH_MEM-1:0] mem_data,
  input mem_data_last,
  input [DATA_WIDTH_MEM/8-1:0] mem_data_strb,

  output dest_data_valid,
  input dest_data_ready,
  output [DATA_WIDTH_DEST-1:0] dest_data,
  output dest_data_last,
  output [DATA_WIDTH_DEST/8-1:0] dest_data_strb
);

/*
 * Resize the data width between the burst memory and the destination interface
 * if necessary.
 */

generate if (DATA_WIDTH_DEST == DATA_WIDTH_MEM)  begin
  assign dest_data_valid = mem_data_valid;
  assign dest_data = mem_data;
  assign dest_data_last = mem_data_last;
  assign dest_data_strb = mem_data_strb;
  assign mem_data_ready = dest_data_ready;
end else begin

  localparam RATIO = DATA_WIDTH_MEM / DATA_WIDTH_DEST;

  reg [$clog2(RATIO)-1:0] count = 'h0;
  reg valid = 1'b0;
  reg [RATIO-1:0] last = 'h0;
  reg [DATA_WIDTH_MEM-1:0] data = 'h0;
  reg [DATA_WIDTH_MEM/8-1:0] strb = {DATA_WIDTH_MEM/8{1'b1}};

  wire last_beat;

  assign last_beat = (count == RATIO - 1) | last[0];

  always @(posedge clk) begin
    if (reset == 1'b1) begin
      valid <= 1'b0;
    end else if (mem_data_valid == 1'b1) begin
      valid <= 1'b1;
    end else if (last_beat == 1'b1 && dest_data_ready == 1'b1) begin
      valid <= 1'b0;
    end
  end

  always @(posedge clk) begin
    if (reset == 1'b1) begin
      count <= 'h0;
    end else if (dest_data_ready == 1'b1 && dest_data_valid == 1'b1) begin
      if (last_beat == 1'b1) begin
        count <= 'h0;
      end else begin
        count <= count + 1;
      end
    end
  end

  assign mem_data_ready = ~valid | (dest_data_ready & last_beat);

  integer i;
  always @(posedge clk) begin
    if (mem_data_ready == 1'b1) begin
      data <= mem_data;

      /*
       * Skip those words where strb would be completely zero for the output
       * word. We assume that strb is thermometer encoded (i.e. a certain number
       * of LSBs are 1'b1 followed by all 1'b0 in the MSBs) and by extension
       * that if the first strb bit for a word is zero that means that all strb
       * bits for a word will be zero.
       */
      for (i = 0; i < RATIO-1; i = i + 1) begin
        last[i] <= mem_data_last & ~mem_data_strb[(i+1)*(DATA_WIDTH_MEM/8/RATIO)];
      end
      last[RATIO-1] <= mem_data_last;
      strb <= mem_data_strb;
    end else if (dest_data_ready == 1'b1) begin
      data[DATA_WIDTH_MEM-DATA_WIDTH_DEST-1:0] <= data[DATA_WIDTH_MEM-1:DATA_WIDTH_DEST];
      strb[(DATA_WIDTH_MEM-DATA_WIDTH_DEST)/8-1:0] <= strb[DATA_WIDTH_MEM/8-1:DATA_WIDTH_DEST/8];
      last[RATIO-2:0] <= last[RATIO-1:1];
    end
  end

  assign dest_data_valid = valid;
  assign dest_data = data[DATA_WIDTH_DEST-1:0];
  assign dest_data_strb = strb[DATA_WIDTH_DEST/8-1:0];
  assign dest_data_last = last[0];

end endgenerate

endmodule
module axi_register_slice #(

  parameter DATA_WIDTH = 32,
  parameter FORWARD_REGISTERED = 0,
  parameter BACKWARD_REGISTERED = 0)(

  input clk,
  input resetn,

  input s_axi_valid,
  output s_axi_ready,
  input [DATA_WIDTH-1:0] s_axi_data,

  output m_axi_valid,
  input m_axi_ready,
  output [DATA_WIDTH-1:0] m_axi_data
);

/*
 s_axi_data  -> bwd_data     -> fwd_data(1)  -> m_axi_data
 s_axi_valid -> bwd_valid    -> fwd_valid(1) -> m_axi_valid
 s_axi_ready <- bwd_ready(2) <- fwd_ready <- m_axi_ready

 (1) FORWARD_REGISTERED inserts a set of FF before m_axi_data and m_axi_valid
 (2) BACKWARD_REGISTERED insters a FF before s_axi_ready
*/

wire [DATA_WIDTH-1:0] bwd_data_s;
wire bwd_valid_s;
wire bwd_ready_s;
wire [DATA_WIDTH-1:0] fwd_data_s;
wire fwd_valid_s;
wire fwd_ready_s;

generate if (FORWARD_REGISTERED == 1) begin

reg fwd_valid = 1'b0;
reg [DATA_WIDTH-1:0] fwd_data = 'h00;

assign fwd_ready_s = ~fwd_valid | m_axi_ready;
assign fwd_valid_s = fwd_valid;
assign fwd_data_s = fwd_data;

always @(posedge clk) begin
  if (~fwd_valid | m_axi_ready)
    fwd_data <= bwd_data_s;
end

always @(posedge clk) begin
  if (resetn == 1'b0) begin
    fwd_valid <= 1'b0;
  end else begin
    if (bwd_valid_s)
      fwd_valid <= 1'b1;
    else if (m_axi_ready)
      fwd_valid <= 1'b0;
  end
end

end else begin
assign fwd_data_s = bwd_data_s;
assign fwd_valid_s = bwd_valid_s;
assign fwd_ready_s = m_axi_ready;
end
endgenerate

generate if (BACKWARD_REGISTERED == 1) begin

reg bwd_ready = 1'b1;
reg [DATA_WIDTH-1:0] bwd_data = 'h00;

assign bwd_valid_s = ~bwd_ready | s_axi_valid;
assign bwd_data_s = bwd_ready ? s_axi_data : bwd_data;
assign bwd_ready_s = bwd_ready;

always @(posedge clk) begin
  if (bwd_ready)
    bwd_data <= s_axi_data;
end

always @(posedge clk) begin
  if (resetn == 1'b0) begin
    bwd_ready <= 1'b1;
  end else begin
    if (fwd_ready_s)
      bwd_ready <= 1'b1;
    else if (s_axi_valid)
      bwd_ready <= 1'b0;
  end
end

end else begin
assign bwd_valid_s = s_axi_valid;
assign bwd_data_s = s_axi_data;
assign bwd_ready_s = fwd_ready_s;
end endgenerate

assign m_axi_data = fwd_data_s;
assign m_axi_valid = fwd_valid_s;
assign s_axi_ready = bwd_ready_s;

endmodule
module debouncer
//----------- Paramters Declarations -------------------------------------------
#(
    parameter DEBOUNCER_LENGTH = 4
)
//----------- Ports Declarations -----------------------------------------------
(
    input       clk_i,
    input       rst_i,
    input       sig_i,
    output reg  sig_o
);
//------------------------------------------------------------------------------
//----------- Registers Declarations -------------------------------------------
//------------------------------------------------------------------------------
reg [DEBOUNCER_LENGTH-1:0] shift_reg;

//------------------------------------------------------------------------------
//----------- Assign/Always Blocks ---------------------------------------------
//------------------------------------------------------------------------------

always @(posedge clk_i)
begin
    if(rst_i == 1)
    begin
        shift_reg   <= 0;
        sig_o       <= 0;
    end
    else
    begin
        shift_reg <= {shift_reg[DEBOUNCER_LENGTH-2:0], sig_i};
        if(shift_reg == {DEBOUNCER_LENGTH{1'b1}})
        begin
            sig_o <= 1'b1;
        end
        else if(shift_reg == {DEBOUNCER_LENGTH{1'b0}})
        begin
            sig_o <= 1'b0;
        end
    end
end

endmodule
module cic_decim (
  input clk,
  input clk_enable,
  input [4:0] filter_enable,
  input reset,
  input [11:0] filter_in,
  input [2:0] rate_sel,
  output [11:0] filter_out,
  output ce_out
  );

  localparam NUM_STAGES = 6;
  localparam DATA_WIDTH = 106;

  reg [11:0] filter_input_stage = 'h00;
  wire signed [DATA_WIDTH-1:0] data_stage[0:NUM_STAGES*2];
  wire signed [DATA_WIDTH-1:0] data_final_stage;

  reg [16:0] counter = 'h00;
  reg ce_comb = 1'b0;

  reg ce_out_reg = 1'b0;
  reg [11:0] data_out = 'h00;

  reg [15:0] rate;

  wire [4:0] enable = (clk_enable == 1'b1) ? filter_enable : 5'b0;

  always @(*) begin
    case (rate_sel)
    3'h1: rate <= 16'd5 - 1;
    3'h2: rate <= 16'd50 - 1;
    3'h3: rate <= 16'd500 - 1;
    3'h6: rate <= 16'd5000 - 1;
    default: rate <= 16'd50000 - 1;
    endcase
  end

  wire [15:0] counter_in = counter[16] == 1'b1 ? rate : counter[15:0];

  always @(posedge clk) begin
    if (reset == 1'b1) begin
      counter <= {1'b1,16'h00};
    end else if (clk_enable == 1'b1 && enable[0] == 1'b1) begin
      counter <= counter_in - 1'b1;
    end
  end

  always @(posedge clk) begin
    if (reset == 1'b1) begin
      ce_comb <= 1'b0;
    end else begin
      ce_comb <= enable[0] & counter[16];
    end
  end

  always @(posedge clk) begin
    if (enable[0] == 1'b1) begin
      filter_input_stage <= filter_in;
    end
  end

  assign data_stage[0] = $signed(filter_input_stage);

  generate
    genvar i;
    for (i = 0; i < NUM_STAGES; i = i + 1) begin
      cic_int #(
        .DATA_WIDTH(DATA_WIDTH),
        .NUM_STAGES(5),
        .STAGE_WIDTH(20)
      ) i_int (
        .clk(clk),
        .ce(enable),
        .data_in(data_stage[i]),
        .data_out(data_stage[i+1])
      );
    end
  endgenerate

  cic_comb #(
    .DATA_WIDTH(DATA_WIDTH),
    .SEQ(5),
    .NUM_STAGES(5),
    .STAGE_WIDTH(20)
  ) i_comb0 (
    .clk(clk),
    .ce(ce_comb),
    .enable(filter_enable),
    .data_in(data_stage[6]),
    .data_out(data_stage[11])
  );

  cic_comb #(
    .DATA_WIDTH(DATA_WIDTH),
    .SEQ(1),
    .NUM_STAGES(5),
    .STAGE_WIDTH(20)
  ) i_comb1 (
    .clk(clk),
    .ce(ce_comb),
    .enable(filter_enable),
    .data_in(data_stage[11]),
    .data_out(data_stage[12])
  );

  assign data_final_stage = data_stage[2*NUM_STAGES];

  always @(posedge clk) begin
    if (ce_comb == 1'b1) begin
      case (rate_sel)
      'h1: data_out <= data_final_stage[25:14];
      'h2: data_out <= data_final_stage[45:34];
      'h3: data_out <= data_final_stage[65:54];
      'h6: data_out <= data_final_stage[85:74];
      default: data_out <= data_final_stage[105:94];
      endcase
    end
    ce_out_reg <= ce_comb;
  end

  assign ce_out = ce_out_reg;
  assign filter_out = data_out;

endmodule  // cic_decim
module util_sigma_delta_spi #(

  parameter NUM_OF_CS = 1,
  parameter CS_PIN = 0,
  parameter IDLE_TIMEOUT = 63 ) (

  input clk,
  input resetn,

  input spi_active,

  input s_sclk,
  input s_sdo,
  input s_sdo_t,
  output s_sdi,
  input [NUM_OF_CS-1:0] s_cs,

  output m_sclk,
  output m_sdo,
  output m_sdo_t,
  input m_sdi,
  output [NUM_OF_CS-1:0] m_cs,

  output reg data_ready);

/*
 * For converters from the ADI SigmaDelta family the data ready interrupt signal
 * uses the same physical wire as the the DOUT signal for the SPI bus. This
 * module extracts the data ready signal from the SPI bus and makes sure to
 * suppress false positives. The data ready signal is indicated by the converter
 * by pulling DOUT low. This will only happen if the CS pin for the converter is
 * low and no SPI transfer is active. There is a small delay between the end of
 * the SPI transfer and the point where the converter starts to indicate the
 * data ready signal. IDLE_TIMEOUT allows to specify the amount of clock cycles
 * the bus needs to be idle before the data ready signal is detected.
 */

assign m_sclk = s_sclk;
assign m_sdo = s_sdo;
assign m_sdo_t = s_sdo_t;
assign s_sdi = m_sdi;
assign m_cs = s_cs;

reg [$clog2(IDLE_TIMEOUT)-1:0] counter = IDLE_TIMEOUT;
reg [2:0] sdi_d = 'h00;

always @(posedge clk) begin
  if (resetn == 1'b0) begin
    counter <= IDLE_TIMEOUT;
  end else begin
    if (s_cs[CS_PIN] == 1'b0 && spi_active == 1'b0) begin
      if (counter != 'h00)
        counter <= counter - 1'b1;
    end else begin
      counter <= IDLE_TIMEOUT;
    end
  end
end

always @(posedge clk) begin
  /* The data ready signal is fully asynchronous */
  sdi_d <= {sdi_d[1:0], m_sdi};
end

always @(posedge clk) begin
  if (counter == 'h00 && sdi_d[2] == 1'b0) begin
    data_ready <= 1'b1;
  end else begin
    data_ready <= 1'b0;
  end
end

endmodule
module ad_mem #(

  parameter  DATA_WIDTH = 16,
  parameter  ADDRESS_WIDTH = 5) (

  input                               clka,
  input                               wea,
  input       [(ADDRESS_WIDTH-1):0]   addra,
  input       [(DATA_WIDTH-1):0]      dina,

  input                               clkb,
  input                               reb,
  input       [(ADDRESS_WIDTH-1):0]   addrb,
  output  reg [(DATA_WIDTH-1):0]      doutb);

  (* ram_style = "block" *)
  reg         [(DATA_WIDTH-1):0]      m_ram[0:((2**ADDRESS_WIDTH)-1)];

  always @(posedge clka) begin
    if (wea == 1'b1) begin
      m_ram[addra] <= dina;
    end
  end

  always @(posedge clkb) begin
    if (reb == 1'b1) begin
      doutb <= m_ram[addrb];
    end
  end

endmodule
module ad_bus_mux #(

  // Channel data width
  parameter DATA_WIDTH = 16) (

  input                    select_path,

  input                    valid_in_0,
  input                    enable_in_0,
  input  [DATA_WIDTH-1:0]  data_in_0,

  input                    valid_in_1,
  input                    enable_in_1,
  input  [DATA_WIDTH-1:0]  data_in_1,

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

  assign valid_out  = (select_path == 0) ? valid_in_0   : valid_in_1;
  assign enable_out = (select_path == 0) ? enable_in_0  : enable_in_1;
  assign data_out   = (select_path == 0) ? data_in_0    : data_in_1;

endmodule
module ad_edge_detect #(

  parameter   EDGE = 0) (

  input                   clk,
  input                   rst,

  input                   signal_in,
  output  reg             signal_out);


  localparam  POS_EDGE = 0;
  localparam  NEG_EDGE = 1;
  localparam  ANY_EDGE = 2;

  reg         ff_m1 = 0;
  reg         ff_m2 = 0;

  always @(posedge clk) begin
    if (rst == 1) begin
      ff_m1 <= 0;
      ff_m2 <= 0;
    end else begin
      ff_m1 <= signal_in;
      ff_m2 <= ff_m1;
    end
  end

  always @(posedge clk) begin
    if (rst == 1) begin
      signal_out <= 1'b0;
    end else begin
      if (EDGE == POS_EDGE) begin
        signal_out <= ff_m1 & ~ff_m2;
      end else if (EDGE == NEG_EDGE) begin
        signal_out <= ~ff_m1 & ff_m2;
      end else begin
        signal_out <= ff_m1 ^ ff_m2;
      end
    end
  end

endmodule
module ad_csc_CrYCb2RGB #(

  parameter   DELAY_DATA_WIDTH = 16) (

  // Cr-Y-Cb inputs

  input                               clk,
  input       [DELAY_DATA_WIDTH-1:0]  CrYCb_sync,
  input       [23:0]                  CrYCb_data,

  // R-G-B outputs

  output      [DELAY_DATA_WIDTH-1:0]  RGB_sync,
  output      [23:0]                  RGB_data);

  localparam  DW = DELAY_DATA_WIDTH - 1;

  // red

  ad_csc  #(
    .DELAY_DW (DELAY_DATA_WIDTH),
    .MUL_COEF_DW (18),
    .SUM_COEF_DW (28),
    .YCbCr_2_RGB (1))
  i_csc_R (
    .clk (clk),
    .sync (CrYCb_sync),
    .data (CrYCb_data),
    .C1 ( 18'd52299),
    .C2 ( 18'd38154),
    .C3 ( 18'd0),
    .C4 (-28'd7304675),
    .csc_sync (RGB_sync),
    .csc_data (RGB_data[23:16]));

  // green

  ad_csc  #(
    .MUL_COEF_DW (18),
    .SUM_COEF_DW (28),
    .YCbCr_2_RGB (1))
  i_csc_G (
    .clk (clk),
    .sync (1'd0),
    .data (CrYCb_data),
    .C1 (-18'd26639),
    .C2 ( 18'd38154),
    .C3 (-18'd12837),
    .C4 ( 28'd4442554),
    .csc_sync (),
    .csc_data (RGB_data[15:8]));

  // blue

  ad_csc #(
    .MUL_COEF_DW (18),
    .SUM_COEF_DW (28),
    .YCbCr_2_RGB (1))
  i_csc_B (
    .clk (clk),
    .sync (1'd0),
    .data (CrYCb_data),
    .C1 ( 18'd0),
    .C2 ( 18'd38154),
    .C3 ( 18'd66101),
    .C4 (-28'd9071362),
    .csc_sync (),
    .csc_data (RGB_data[7:0]));

endmodule
module ad_3w_spi #(

  parameter NUM_OF_SLAVES=8) (

  input       [NUM_OF_SLAVES-1:0] spi_csn,
  input                           spi_clk,
  input                           spi_mosi,
  output                          spi_miso,

  inout                           spi_sdio,
  output                          spi_dir);

  // internal registers

  reg     [ 5:0]  spi_count = 'd0;
  reg             spi_rd_wr_n = 'd0;
  reg             spi_enable = 'd0;

  // internal signals

  wire            spi_csn_s;
  wire            spi_enable_s;

  // check on rising edge and change on falling edge

  assign spi_csn_s = & spi_csn;
  assign spi_dir = ~spi_enable_s;
  assign spi_enable_s = spi_enable & ~spi_csn_s;

  always @(posedge spi_clk or posedge spi_csn_s) begin
    if (spi_csn_s == 1'b1) begin
      spi_count <= 6'd0;
      spi_rd_wr_n <= 1'd0;
    end else begin
      spi_count <= (spi_count < 6'h3f) ? spi_count + 1'b1 : spi_count;
      if (spi_count == 6'd0) begin
        spi_rd_wr_n <= spi_mosi;
      end
    end
  end

  always @(negedge spi_clk or posedge spi_csn_s) begin
    if (spi_csn_s == 1'b1) begin
      spi_enable <= 1'b0;
    end else begin
      if (spi_count == 6'd16) begin
        spi_enable <= spi_rd_wr_n;
      end
    end
  end

  // io butter

  assign spi_miso = spi_sdio;
  assign spi_sdio = (spi_enable_s == 1'b1) ? 1'bz : spi_mosi;

endmodule
module ad_dds_cordic_pipe#(

  // parameters

  // Range = N/A
  parameter P_DW = 16,
  // Range = N/A
  parameter D_DW = 16,
  // Range = N/A
  parameter DELAY_DW = 1,
  // Range = 0-(DW - 1)
  parameter SHIFT = 0) (

  // Interface

                      input                          clk,
  (* keep = "TRUE" *) input                          dir,
  (* keep = "TRUE" *) input             [  D_DW-1:0] dataa_x,
  (* keep = "TRUE" *) input             [  D_DW-1:0] dataa_y,
  (* keep = "TRUE" *) input             [  P_DW-1:0] dataa_z,
  (* keep = "TRUE" *) input             [  P_DW-1:0] datab_z,
  (* keep = "TRUE" *) output reg        [  D_DW-1:0] result_x,
  (* keep = "TRUE" *) output reg        [  D_DW-1:0] result_y,
  (* keep = "TRUE" *) output reg        [  P_DW-1:0] result_z,
                      input             [DELAY_DW:1] data_delay_in,
                      output            [DELAY_DW:1] data_delay_out);

  // Registers Declarations

  reg   [DELAY_DW:1] data_delay = 'd0;

  // Wires Declarations

  wire  [  D_DW-1:0]  sgn_shift_x;
  wire  [  D_DW-1:0]  sgn_shift_y;
  wire                dir_inv = ~dir;

  // Sign shift

  assign sgn_shift_x = {{SHIFT{dataa_x[D_DW-1]}}, dataa_x[D_DW-1:SHIFT]};
  assign sgn_shift_y = {{SHIFT{dataa_y[D_DW-1]}}, dataa_y[D_DW-1:SHIFT]};

  // Stage rotation

  always @(posedge clk) begin
    result_x <= dataa_x + ({D_DW{dir_inv}} ^ sgn_shift_y) + dir_inv;
    result_y <= dataa_y + ({D_DW{dir}}     ^ sgn_shift_x) + dir;
    result_z <= dataa_z + ({P_DW{dir_inv}} ^     datab_z) + dir_inv;
  end

  // Delay data (if used)

  generate
    if (DELAY_DW > 1) begin
      always @(posedge clk) begin
        data_delay <= data_delay_in;
      end
    end
  endgenerate

  assign data_delay_out = data_delay;

endmodule
module ad_g2b #(

  parameter DATA_WIDTH = 8) (

  input       [DATA_WIDTH-1:0]    din,
  output      [DATA_WIDTH-1:0]    dout);

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

  assign dout = g2b(din);

endmodule
module ad_ss_422to444 #(

  parameter   CR_CB_N = 0,
  parameter   DELAY_DATA_WIDTH = 16) (

  // 422 inputs

  input                               clk,
  input                               s422_de,
  input       [DELAY_DATA_WIDTH-1:0]  s422_sync,
  input       [                15:0]  s422_data,

  // 444 outputs

  output  reg [DELAY_DATA_WIDTH-1:0]  s444_sync,
  output  reg [                23:0]  s444_data);

  localparam  DW = DELAY_DATA_WIDTH - 1;

  // internal registers

  reg             cr_cb_sel = 'd0;
  reg             s422_de_d = 'd0;
  reg     [DW:0]  s422_sync_d = 'd0;
  reg             s422_de_2d = 'd0;
  reg      [7:0]  s422_Y_d;
  reg      [7:0]  s422_CbCr_d;
  reg      [7:0]  s422_CbCr_2d;
  reg     [ 8:0]  s422_CbCr_avg;

  // internal wires

  wire    [ 7:0]  s422_Y;
  wire    [ 7:0]  s422_CbCr;

  // Input format is
  // [15:8] Cb/Cr
  // [ 7:0] Y
  //
  // Output format is
  // [23:15] Cr
  // [16: 8] Y
  // [ 7: 0] Cb

  assign s422_Y = s422_data[7:0];
  assign s422_CbCr = s422_data[15:8];

  // first data on de assertion is cb (0x0), then cr (0x1).
  // previous data is held when not current

  always @(posedge clk) begin
    if (s422_de_d == 1'b1) begin
      cr_cb_sel <= ~cr_cb_sel;
    end else begin
      cr_cb_sel <= CR_CB_N;
    end
  end

  // pipe line stages

  always @(posedge clk) begin
    s422_de_d <= s422_de;
    s422_sync_d <= s422_sync;
    s422_de_2d <= s422_de_d;
    s422_Y_d <= s422_Y;

    s422_CbCr_d <= s422_CbCr;
    s422_CbCr_2d <= s422_CbCr_d;
  end

  // If both the left and the right sample are valid do the average, otherwise
  // use the only valid.
  always @(s422_de_2d, s422_de, s422_CbCr, s422_CbCr_2d)
  begin
    if (s422_de == 1'b1 && s422_de_2d)
      s422_CbCr_avg <= s422_CbCr + s422_CbCr_2d;
    else if (s422_de == 1'b1)
      s422_CbCr_avg <= {s422_CbCr, 1'b0};
    else
      s422_CbCr_avg <= {s422_CbCr_2d, 1'b0};
  end

  // 444 outputs

  always @(posedge clk) begin
    s444_sync <= s422_sync_d;
    s444_data[15:8] <= s422_Y_d;
    if (cr_cb_sel) begin
      s444_data[23:16] <= s422_CbCr_d;
      s444_data[ 7: 0] <= s422_CbCr_avg[8:1];
    end else begin
      s444_data[23:16] <= s422_CbCr_avg[8:1];
      s444_data[ 7: 0] <= s422_CbCr_d;
    end
  end

endmodule
module ad_mem_asym #(

  parameter   A_ADDRESS_WIDTH =  8,
  parameter   A_DATA_WIDTH = 256,
  parameter   B_ADDRESS_WIDTH =   10,
  parameter   B_DATA_WIDTH =  64) (

  input                             clka,
  input                             wea,
  input       [A_ADDRESS_WIDTH-1:0] addra,
  input       [A_DATA_WIDTH-1:0]    dina,

  input                             clkb,
  input                             reb,
  input       [B_ADDRESS_WIDTH-1:0] addrb,
  output  reg [B_DATA_WIDTH-1:0]    doutb);


  `define max(a,b) {(a) > (b) ? (a) : (b)}
  `define min(a,b) {(a) < (b) ? (a) : (b)}

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

  localparam  MEM_ADDRESS_WIDTH = `max(A_ADDRESS_WIDTH, B_ADDRESS_WIDTH);
  localparam  MIN_WIDTH = `min(A_DATA_WIDTH, B_DATA_WIDTH);
  localparam  MAX_WIDTH = `max(A_DATA_WIDTH, B_DATA_WIDTH);
  localparam  MEM_DATA_WIDTH = MIN_WIDTH;
  localparam  MEM_SIZE = 2 ** MEM_ADDRESS_WIDTH;
  localparam  MEM_RATIO = MAX_WIDTH / MIN_WIDTH;
  localparam  MEM_RATIO_LOG2 = clog2(MEM_RATIO);

  // internal registers

  (* ram_style = "block" *)
  reg      [MEM_DATA_WIDTH-1:0]    m_ram[0:MEM_SIZE-1];

  //---------------------------------------------------------------------------
  // write interface
  //---------------------------------------------------------------------------

  // write data width is narrower than read data width
  generate if (A_DATA_WIDTH <= B_DATA_WIDTH) begin
    always @(posedge clka) begin
      if (wea == 1'b1) begin
        m_ram[addra] <= dina;
      end
    end
  end
  endgenerate

  // write data width is wider than read data width
  generate if (A_DATA_WIDTH > B_DATA_WIDTH) begin
    always @(posedge clka) begin : memwrite
      integer i;
      reg [MEM_RATIO_LOG2-1:0] lsb;
      for (i = 0; i < MEM_RATIO; i = i + 1) begin : awrite
        lsb = i;
        if (wea) begin
          m_ram[{addra, lsb}] <= dina[i * MIN_WIDTH +: MIN_WIDTH];
        end
      end
    end
  end
  endgenerate

  //---------------------------------------------------------------------------
  // read interface
  //---------------------------------------------------------------------------

  // read data width is narrower than write data width
  generate if (A_DATA_WIDTH >= B_DATA_WIDTH) begin
    always @(posedge clkb) begin
      if (reb == 1'b1) begin
        doutb <= m_ram[addrb];
      end
    end
  end
  endgenerate

  // read data width is wider than write data width
  generate if (A_DATA_WIDTH < B_DATA_WIDTH) begin
    always @(posedge clkb) begin : memread
      integer i;
      reg [MEM_RATIO_LOG2-1:0] lsb;
      for (i = 0; i < MEM_RATIO; i = i + 1) begin : aread
        lsb = i;
        if (reb == 1'b1) begin
          doutb[i*MIN_WIDTH +: MIN_WIDTH] <= m_ram[{addrb, lsb}];
        end
      end
    end
  end
  endgenerate

endmodule
module ad_perfect_shuffle #(
  parameter NUM_GROUPS = 2,
  parameter WORDS_PER_GROUP = 2,
  parameter WORD_WIDTH = 8
) (
  input [NUM_GROUPS*WORDS_PER_GROUP*WORD_WIDTH-1:0] data_in,
  output [NUM_GROUPS*WORDS_PER_GROUP*WORD_WIDTH-1:0] data_out
);
 /*
  * Performs the perfect shuffle operation.
  *
  * The perfect shuffle splits the input vector into NUM_GROUPS groups and then
  * each group in WORDS_PER_GROUP. The output vector consists of WORDS_PER_GROUP
  * groups and each group has NUM_GROUPS words. The data is remapped, so that
  * the i-th word of the j-th word in the output vector is the j-th word of the
  * i-th group of the input vector.

  * The inverse operation of the perfect shuffle is the perfect shuffle with
  * both parameters swapped.
  * I.e. [perfect_suffle B A [perfect_shuffle A B data]] == data
  *
  * Examples:
  *   NUM_GROUPS = 2, WORDS_PER_GROUP = 4
  *     [A B C D a b c d] => [A a B b C c D d]
  *   NUM_GROUPS = 4, WORDS_PER_GROUP = 2
  *     [A a B b C c D d] => [A B C D a b c d]
  *   NUM_GROUPS = 3, WORDS_PER_GROUP = 2
  *     [A B a b 1 2] => [A a 1 B b 2]
  */
  generate
    genvar i;
    genvar j;
    for (i = 0; i < NUM_GROUPS; i = i + 1) begin: shuffle_outer
      for (j = 0; j < WORDS_PER_GROUP; j = j + 1) begin: shuffle_inner
        localparam src_lsb = (j + i * WORDS_PER_GROUP) * WORD_WIDTH;
        localparam dst_lsb = (i + j * NUM_GROUPS) * WORD_WIDTH;

        assign data_out[dst_lsb+:WORD_WIDTH] = data_in[src_lsb+:WORD_WIDTH];
      end
    end
  endgenerate

endmodule
module ad_datafmt #(

  // data bus width

  parameter   DATA_WIDTH = 16,
  parameter   OCTETS_PER_SAMPLE = 2,
  parameter   DISABLE = 0) (

  // data path

  input                       clk,
  input                       valid,
  input   [(DATA_WIDTH-1):0]  data,
  output                      valid_out,
  output  [(8*OCTETS_PER_SAMPLE-1):0]  data_out,

  // control signals

  input                       dfmt_enable,
  input                       dfmt_type,
  input                       dfmt_se);

  // internal registers

  reg                         valid_int = 'd0;
  reg     [(8*OCTETS_PER_SAMPLE-1):0]  data_int = 'd0;

  // internal signals

  wire                        type_s;
  wire    [(8*OCTETS_PER_SAMPLE-1):0]  data_out_s;

  // data-path disable

  generate
  if (DISABLE == 1) begin
  assign valid_out = valid;
  assign data_out = data;
  end else begin
  assign valid_out = valid_int;
  assign data_out = data_int;
  end
  endgenerate

  // if offset-binary convert to 2's complement first

  assign type_s = dfmt_enable & dfmt_type;

  generate
  if (DATA_WIDTH < 8*OCTETS_PER_SAMPLE) begin
    wire signext_s;
    wire sign_s;

    assign signext_s = dfmt_enable & dfmt_se;
    assign sign_s = signext_s & (type_s ^ data[(DATA_WIDTH-1)]);
    assign data_out_s[(8*OCTETS_PER_SAMPLE-1):DATA_WIDTH] = {((8*OCTETS_PER_SAMPLE)-DATA_WIDTH){sign_s}};
  end
  endgenerate

  assign data_out_s[(DATA_WIDTH-1)] = type_s ^ data[(DATA_WIDTH-1)];
  assign data_out_s[(DATA_WIDTH-2):0] = data[(DATA_WIDTH-2):0];

  always @(posedge clk) begin
    valid_int <= valid;
    data_int <= data_out_s;
  end

endmodule
module up_xfer_cntrl #(

  parameter     DATA_WIDTH = 8) (

  // up interface

  input                       up_rstn,
  input                       up_clk,
  input   [(DATA_WIDTH-1):0]  up_data_cntrl,
  output                      up_xfer_done,

  // device interface

  input                       d_rst,
  input                       d_clk,
  output  [(DATA_WIDTH-1):0]  d_data_cntrl);

  // internal registers

  reg                         up_xfer_state_m1 = 'd0;
  reg                         up_xfer_state_m2 = 'd0;
  reg                         up_xfer_state = 'd0;
  reg     [ 5:0]              up_xfer_count = 'd0;
  reg                         up_xfer_done_int = 'd0;
  reg                         up_xfer_toggle = 'd0;
  reg     [(DATA_WIDTH-1):0]  up_xfer_data = 'd0;
  reg                         d_xfer_toggle_m1 = 'd0;
  reg                         d_xfer_toggle_m2 = 'd0;
  reg                         d_xfer_toggle_m3 = 'd0;
  reg                         d_xfer_toggle = 'd0;
  reg     [(DATA_WIDTH-1):0]  d_data_cntrl_int = 'd0;

  // internal signals

  wire                        up_xfer_enable_s;
  wire                        d_xfer_toggle_s;

  // device control transfer

  assign up_xfer_done = up_xfer_done_int;
  assign up_xfer_enable_s = up_xfer_state ^ up_xfer_toggle;

  always @(posedge up_clk) begin
    if (up_rstn == 1'b0) begin
      up_xfer_state_m1 <= 'd0;
      up_xfer_state_m2 <= 'd0;
      up_xfer_state <= 'd0;
      up_xfer_count <= 'd0;
      up_xfer_done_int <= 'd0;
      up_xfer_toggle <= 'd0;
      up_xfer_data <= 'd0;
    end else begin
      up_xfer_state_m1 <= d_xfer_toggle;
      up_xfer_state_m2 <= up_xfer_state_m1;
      up_xfer_state <= up_xfer_state_m2;
      up_xfer_count <= up_xfer_count + 1'd1;
      up_xfer_done_int <= (up_xfer_count == 6'd1) ? ~up_xfer_enable_s : 1'b0;
      if ((up_xfer_count == 6'd1) && (up_xfer_enable_s == 1'b0)) begin
        up_xfer_toggle <= ~up_xfer_toggle;
        up_xfer_data <= up_data_cntrl;
      end
    end
  end

  assign d_data_cntrl = d_data_cntrl_int;
  assign d_xfer_toggle_s = d_xfer_toggle_m3 ^ d_xfer_toggle_m2;

  always @(posedge d_clk or posedge d_rst) begin
    if (d_rst == 1'b1) begin
      d_xfer_toggle_m1 <= 'd0;
      d_xfer_toggle_m2 <= 'd0;
      d_xfer_toggle_m3 <= 'd0;
      d_xfer_toggle <= 'd0;
      d_data_cntrl_int <= 'd0;
    end else begin
      d_xfer_toggle_m1 <= up_xfer_toggle;
      d_xfer_toggle_m2 <= d_xfer_toggle_m1;
      d_xfer_toggle_m3 <= d_xfer_toggle_m2;
      d_xfer_toggle <= d_xfer_toggle_m3;
      if (d_xfer_toggle_s == 1'b1) begin
        d_data_cntrl_int <= up_xfer_data;
      end
    end
  end

endmodule
module up_xfer_status #(

  parameter     DATA_WIDTH = 8) (

  // up interface

  input                       up_rstn,
  input                       up_clk,
  output  [(DATA_WIDTH-1):0]  up_data_status,

  // device interface

  input                       d_rst,
  input                       d_clk,
  input   [(DATA_WIDTH-1):0]  d_data_status);

  // internal registers

  reg                         d_xfer_state_m1 = 'd0;
  reg                         d_xfer_state_m2 = 'd0;
  reg                         d_xfer_state = 'd0;
  reg     [ 5:0]              d_xfer_count = 'd0;
  reg                         d_xfer_toggle = 'd0;
  reg     [(DATA_WIDTH-1):0]  d_xfer_data = 'd0;
  reg     [(DATA_WIDTH-1):0]  d_acc_data = 'd0;
  reg                         up_xfer_toggle_m1 = 'd0;
  reg                         up_xfer_toggle_m2 = 'd0;
  reg                         up_xfer_toggle_m3 = 'd0;
  reg                         up_xfer_toggle = 'd0;
  reg     [(DATA_WIDTH-1):0]  up_data_status_int = 'd0;

  // internal signals

  wire                        d_xfer_enable_s;
  wire                        up_xfer_toggle_s;

  // device status transfer

  assign d_xfer_enable_s = d_xfer_state ^ d_xfer_toggle;

  always @(posedge d_clk or posedge d_rst) begin
    if (d_rst == 1'b1) begin
      d_xfer_state_m1 <= 'd0;
      d_xfer_state_m2 <= 'd0;
      d_xfer_state <= 'd0;
      d_xfer_count <= 'd0;
      d_xfer_toggle <= 'd0;
      d_xfer_data <= 'd0;
      d_acc_data <= 'd0;
    end else begin
      d_xfer_state_m1 <= up_xfer_toggle;
      d_xfer_state_m2 <= d_xfer_state_m1;
      d_xfer_state <= d_xfer_state_m2;
      d_xfer_count <= d_xfer_count + 1'd1;
      if ((d_xfer_count == 6'd1) && (d_xfer_enable_s == 1'b0)) begin
        d_xfer_toggle <= ~d_xfer_toggle;
        d_xfer_data <= d_acc_data;
      end
      if ((d_xfer_count == 6'd1) && (d_xfer_enable_s == 1'b0)) begin
        d_acc_data <= d_data_status;
      end else begin
        d_acc_data <= d_acc_data | d_data_status;
      end
    end
  end

  assign up_data_status = up_data_status_int;
  assign up_xfer_toggle_s = up_xfer_toggle_m3 ^ up_xfer_toggle_m2;

  always @(posedge up_clk) begin
    if (up_rstn == 1'b0) begin
      up_xfer_toggle_m1 <= 'd0;
      up_xfer_toggle_m2 <= 'd0;
      up_xfer_toggle_m3 <= 'd0;
      up_xfer_toggle <= 'd0;
      up_data_status_int <= 'd0;
    end else begin
      up_xfer_toggle_m1 <= d_xfer_toggle;
      up_xfer_toggle_m2 <= up_xfer_toggle_m1;
      up_xfer_toggle_m3 <= up_xfer_toggle_m2;
      up_xfer_toggle <= up_xfer_toggle_m3;
      if (up_xfer_toggle_s == 1'b1) begin
        up_data_status_int <= d_xfer_data;
      end
    end
  end

endmodule
module ad_ss_444to422 #(

  parameter   CR_CB_N = 0,
  parameter   DELAY_DATA_WIDTH = 16) (

  // 444 inputs

  input                               clk,
  input                               s444_de,
  input       [DELAY_DATA_WIDTH-1:0]  s444_sync,
  input       [23:0]                  s444_data,

  // 422 outputs

  output  reg [DELAY_DATA_WIDTH-1:0]  s422_sync,
  output  reg [15:0]                  s422_data);

  localparam  DW = DELAY_DATA_WIDTH - 1;

  // internal registers

  reg             s444_de_d = 'd0;
  reg     [DW:0]  s444_sync_d = 'd0;
  reg     [23:0]  s444_data_d = 'd0;
  reg             s444_de_2d = 'd0;
  reg     [DW:0]  s444_sync_2d = 'd0;
  reg     [23:0]  s444_data_2d = 'd0;
  reg             s444_de_3d = 'd0;
  reg     [DW:0]  s444_sync_3d = 'd0;
  reg     [23:0]  s444_data_3d = 'd0;
  reg     [ 7:0]  cr = 'd0;
  reg     [ 7:0]  cb = 'd0;
  reg             cr_cb_sel = 'd0;

  // internal wires

  wire    [ 9:0]  cr_s;
  wire    [ 9:0]  cb_s;

  // fill the data pipe lines, hold the last data on edges

  always @(posedge clk) begin
    s444_de_d <= s444_de;
    s444_sync_d <= s444_sync;
    if (s444_de == 1'b1) begin
      s444_data_d <= s444_data;
    end
    s444_de_2d <= s444_de_d;
    s444_sync_2d <= s444_sync_d;
    if (s444_de_d == 1'b1) begin
      s444_data_2d <= s444_data_d;
    end
    s444_de_3d <= s444_de_2d;
    s444_sync_3d <= s444_sync_2d;
    if (s444_de_2d == 1'b1) begin
      s444_data_3d <= s444_data_2d;
    end
  end

  // get the average 0.25*s(n-1) + 0.5*s(n) + 0.25*s(n+1)

  assign cr_s = {2'd0, s444_data_d[23:16]} +
                {2'd0, s444_data_3d[23:16]} +
                {1'd0, s444_data_2d[23:16], 1'd0};

  assign cb_s = {2'd0, s444_data_d[7:0]} +
                {2'd0, s444_data_3d[7:0]} +
                {1'd0, s444_data_2d[7:0], 1'd0};

  always @(posedge clk) begin
    cr <= cr_s[9:2];
    cb <= cb_s[9:2];
    if (s444_de_3d == 1'b1) begin
      cr_cb_sel <= ~cr_cb_sel;
    end else begin
      cr_cb_sel <= CR_CB_N;
    end
  end

  // 422 outputs

  always @(posedge clk) begin
    s422_sync <= s444_sync_3d;
    if (s444_de_3d == 1'b0) begin
      s422_data <= 'd0;
    end else if (cr_cb_sel == 1'b1) begin
      s422_data <= {cr, s444_data_3d[15:8]};
    end else begin
      s422_data <= {cb, s444_data_3d[15:8]};
    end
  end

endmodule