dakies/OSS_Verilog huggingface dataset:
module util_axis_resize (
  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
);

parameter MASTER_DATA_WIDTH = 64;
parameter SLAVE_DATA_WIDTH = 64;
parameter BIG_ENDIAN = 0;

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

localparam RATIO = MASTER_DATA_WIDTH / SLAVE_DATA_WIDTH;

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

localparam RATIO = SLAVE_DATA_WIDTH / MASTER_DATA_WIDTH;

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 fifo_address_sync (
  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
);

parameter ADDRESS_WIDTH = 4;

reg [ADDRESS_WIDTH:0] room = 2**ADDRESS_WIDTH;
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 <= 2**ADDRESS_WIDTH;
    s_axis_empty <= 'h00;
  end else begin
    level <= level_next;
    room <= 2**ADDRESS_WIDTH - level_next;
    m_axis_valid <= level_next != 0;
    s_axis_ready <= level_next != 2**ADDRESS_WIDTH;
    s_axis_empty <= level_next == 0;
  end
end

endmodule
module fifo_address_gray (
  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
);

parameter ADDRESS_WIDTH = 4;

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(s_axis_waddr_gray),
  .out(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(m_axis_raddr_gray),
  .out(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 sync_gray (
  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
);

// 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;

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 = ASYNC_CLK ? out_count_m : in_count;

endmodule
module fifo_address_gray_pipelined (
  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
);

parameter ADDRESS_WIDTH = 4;

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;
  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;
  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 <= 2**ADDRESS_WIDTH;
  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 + 2**ADDRESS_WIDTH;
  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 lm32_adder (
    // ----- Inputs -------
    adder_op_x,
    adder_op_x_n,
    operand_0_x,
    operand_1_x,
    // ----- Outputs -------
    adder_result_x,
    adder_carry_n_x,
    adder_overflow_x
    );

/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////

input adder_op_x;                                       // Operating to perform, 0 for addition, 1 for subtraction
input adder_op_x_n;                                     // Inverted version of adder_op_x
input [`LM32_WORD_RNG] operand_0_x;                     // Operand to add, or subtract from
input [`LM32_WORD_RNG] operand_1_x;                     // Opearnd to add, or subtract by

/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////

output [`LM32_WORD_RNG] adder_result_x;                 // Result of addition or subtraction
wire   [`LM32_WORD_RNG] adder_result_x;
output adder_carry_n_x;                                 // Inverted carry
wire   adder_carry_n_x;
output adder_overflow_x;                                // Indicates if overflow occured, only valid for subtractions
reg    adder_overflow_x;
    
/////////////////////////////////////////////////////
// Internal nets and registers 
/////////////////////////////////////////////////////

wire a_sign;                                            // Sign (i.e. positive or negative) of operand 0
wire b_sign;                                            // Sign of operand 1
wire result_sign;                                       // Sign of result

/////////////////////////////////////////////////////
// Instantiations 
/////////////////////////////////////////////////////

lm32_addsub addsub (
    // ----- Inputs -----
    .DataA          (operand_0_x), 
    .DataB          (operand_1_x), 
    .Cin            (adder_op_x), 
    .Add_Sub        (adder_op_x_n), 
    // ----- Ouputs -----
    .Result         (adder_result_x), 
    .Cout           (adder_carry_n_x)
    );

/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////

// Extract signs of operands and result

assign a_sign = operand_0_x[`LM32_WORD_WIDTH-1];
assign b_sign = operand_1_x[`LM32_WORD_WIDTH-1];
assign result_sign = adder_result_x[`LM32_WORD_WIDTH-1];

// Determine whether an overflow occured when performing a subtraction

always @(*)
begin    
    //  +ve - -ve = -ve -> overflow
    //  -ve - +ve = +ve -> overflow
    if  (   (!a_sign & b_sign & result_sign)
         || (a_sign & !b_sign & !result_sign)
        )
        adder_overflow_x = `TRUE;
    else
        adder_overflow_x = `FALSE;
end
    
endmodule
module lm32_addsub (
    // ----- Inputs -------
    DataA, 
    DataB, 
    Cin, 
    Add_Sub, 
    // ----- Outputs -------
    Result, 
    Cout
    );

/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////

input [31:0] DataA;
input [31:0] DataB;
input Cin;
input Add_Sub;

/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////

output [31:0] Result;
wire   [31:0] Result;
output Cout;
wire   Cout;

/////////////////////////////////////////////////////
// Instantiations
///////////////////////////////////////////////////// 

// Modified for Milkymist: removed non-portable instantiated block
	     wire [32:0] tmp_addResult = DataA + DataB + Cin;
	     wire [32:0] tmp_subResult = DataA - DataB - !Cin;   
   
	     assign  Result = (Add_Sub == 1) ? tmp_addResult[31:0] : tmp_subResult[31:0];
	     assign  Cout = (Add_Sub == 1) ? tmp_addResult[32] : !tmp_subResult[32];

endmodule
module jtag_cores (
    input [7:0] reg_d,
    input [2:0] reg_addr_d,
    output reg_update,
    output [7:0] reg_q,
    output [2:0] reg_addr_q,
    output jtck,
    output jrstn
);

wire tck;
wire tdi;
wire tdo;
wire capture;
wire shift;
wire update;
wire e1dr;
wire reset;

jtag_tap jtag_tap (
	.tck(tck),
	.tdi(tdi),
	.tdo(tdo),
	.capture(capture),
	.shift(shift),
	.e1dr(e1dr),
	.update(update),
	.reset(reset)
);

reg [10:0] jtag_shift;
reg [10:0] jtag_latched;

always @(posedge tck)
begin
	if(reset)
		jtag_shift <= 11'b0;
	else begin
		if (shift)
			jtag_shift <= {tdi, jtag_shift[10:1]};
		else if (capture)
			jtag_shift <= {reg_d, reg_addr_d};
	end
end

assign tdo = jtag_shift[0];

always @(posedge tck)
begin
	if(reset)
		jtag_latched <= 11'b0;
	else begin
	   if (e1dr)
		   jtag_latched <= jtag_shift;
	end
end

assign reg_update = update;
assign reg_q = jtag_latched[10:3];
assign reg_addr_q = jtag_latched[2:0];
assign jtck = tck;
assign jrstn = ~reset;

endmodule
module lm32_logic_op (
    // ----- Inputs -------
    logic_op_x,
    operand_0_x,
    operand_1_x,
    // ----- Outputs -------
    logic_result_x
    );

/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////

input [`LM32_LOGIC_OP_RNG] logic_op_x;
input [`LM32_WORD_RNG] operand_0_x;
input [`LM32_WORD_RNG] operand_1_x;

/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////

output [`LM32_WORD_RNG] logic_result_x;
reg    [`LM32_WORD_RNG] logic_result_x;
    
/////////////////////////////////////////////////////
// Internal nets and registers 
/////////////////////////////////////////////////////

integer logic_idx;

/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////

always @(*)
begin
    for(logic_idx = 0; logic_idx < `LM32_WORD_WIDTH; logic_idx = logic_idx + 1)
        logic_result_x[logic_idx] = logic_op_x[{operand_1_x[logic_idx], operand_0_x[logic_idx]}];
end
    
endmodule
module jtag_tap(
  output tck,
  output tdi,
  input tdo,
  output capture,
  output shift,
  output e1dr,
  output update,
  output reset
);

	assign tck = 1;
	assign tdi = 1;
	assign capture = 0;
	assign shift = 0;
	assign e1dr = 0;
	assign update = 0;
	assign reset = 0;

endmodule
module spi_clgen (clk_in, rst, go, enable, last_clk, divider, clk_out, pos_edge, neg_edge); 

  input                            clk_in;   // input clock (system clock)
  input                            rst;      // reset
  input                            enable;   // clock enable
  input                            go;       // start transfer
  input                            last_clk; // last clock
  input     [`SPI_DIVIDER_LEN-1:0] divider;  // clock divider (output clock is divided by this value)
  output                           clk_out;  // output clock
  output                           pos_edge; // pulse marking positive edge of clk_out
  output                           neg_edge; // pulse marking negative edge of clk_out
                            
  reg                              clk_out;
  reg                              pos_edge;
  reg                              neg_edge;
                            
  reg       [`SPI_DIVIDER_LEN-1:0] cnt;      // clock counter 
  wire                             cnt_zero; // conter is equal to zero
  wire                             cnt_one;  // conter is equal to one
  
  
  assign cnt_zero = cnt == {`SPI_DIVIDER_LEN{1'b0}};
  assign cnt_one  = cnt == {{`SPI_DIVIDER_LEN-1{1'b0}}, 1'b1};
  
  // Counter counts half period
  always @(posedge clk_in)
  begin
    if(rst)
      cnt <= {`SPI_DIVIDER_LEN{1'b1}};
    else
      begin
        if(!enable || cnt_zero)
          cnt <= divider;
        else
          cnt <= cnt - {{`SPI_DIVIDER_LEN-1{1'b0}}, 1'b1};
      end
  end
  
  // clk_out is asserted every other half period
  always @(posedge clk_in)
  begin
    if(rst)
      clk_out <= 1'b0;
    else
      clk_out <= (enable && cnt_zero && (!last_clk || clk_out)) ? ~clk_out : clk_out;
  end
   
  // Pos and neg edge signals
  always @(posedge clk_in)
  begin
    if(rst)
      begin
        pos_edge  <= 1'b0;
        neg_edge  <= 1'b0;
      end
    else
      begin
        pos_edge  <= (enable && !clk_out && cnt_one) || (!(|divider) && clk_out) || (!(|divider) && go && !enable);
        neg_edge  <= (enable && clk_out && cnt_one) || (!(|divider) && !clk_out && enable);
      end
  end
endmodule
module wb_master_model(clk, rst, adr, din, dout, cyc, stb, we, sel, ack, err, rty);

  parameter dwidth = 32;
  parameter awidth = 32;
  
  input                  clk, rst;
  output [awidth   -1:0] adr;
  input  [dwidth   -1:0] din;
  output [dwidth   -1:0] dout;
  output                 cyc, stb;
  output                 we;
  output [dwidth/8 -1:0] sel;
  input                  ack, err, rty;
  
  // Internal signals
  reg    [awidth   -1:0] adr;
  reg    [dwidth   -1:0] dout;
  reg                    cyc, stb;
  reg                    we;
  reg    [dwidth/8 -1:0] sel;
         
  reg    [dwidth   -1:0] q;
  
  // Memory Logic
  initial
    begin
      adr  = {awidth{1'bx}};
      dout = {dwidth{1'bx}};
      cyc  = 1'b0;
      stb  = 1'bx;
      we   = 1'hx;
      sel  = {dwidth/8{1'bx}};
      #1;
    end
  
  // Wishbone write cycle
  task wb_write;
    input   delay;
    integer delay;
  
    input [awidth -1:0] a;
    input [dwidth -1:0] d;
  
    begin
  
      // wait initial delay
      repeat(delay) @(posedge clk);
  
      // assert wishbone signal
      #1;
      adr  = a;
      dout = d;
      cyc  = 1'b1;
      stb  = 1'b1;
      we   = 1'b1;
      sel  = {dwidth/8{1'b1}};
      @(posedge clk);
  
      // wait for acknowledge from slave
      while(~ack) @(posedge clk);
  
      // negate wishbone signals
      #1;
      cyc  = 1'b0;
      stb  = 1'bx;
      adr  = {awidth{1'bx}};
      dout = {dwidth{1'bx}};
      we   = 1'hx;
      sel  = {dwidth/8{1'bx}};
  
    end
  endtask
  
  // Wishbone read cycle
  task wb_read;
    input   delay;
    integer delay;
  
    input  [awidth -1:0]  a;
    output  [dwidth -1:0] d;
  
    begin
  
      // wait initial delay
      repeat(delay) @(posedge clk);
  
      // assert wishbone signals
      #1;
      adr  = a;
      dout = {dwidth{1'bx}};
      cyc  = 1'b1;
      stb  = 1'b1;
      we   = 1'b0;
      sel  = {dwidth/8{1'b1}};
      @(posedge clk);
  
      // wait for acknowledge from slave
      while(~ack) @(posedge clk);
  
      // negate wishbone signals
      #1;
      cyc  = 1'b0;
      stb  = 1'bx;
      adr  = {awidth{1'bx}};
      dout = {dwidth{1'bx}};
      we   = 1'hx;
      sel  = {dwidth/8{1'bx}};
      d    = din;
  
    end
  endtask
  
  // Wishbone compare cycle (read data from location and compare with expected data)
  task wb_cmp;
    input   delay;
    integer delay;
  
    input [awidth -1:0] a;
    input [dwidth -1:0] d_exp;
  
    begin
      wb_read (delay, a, q);

    if (d_exp !== q)
      $display("Data compare error. Received %h, expected %h at time %t", q, d_exp, $time);
    end
  endtask
  
endmodule
module spi_slave_model (rst, ss, sclk, mosi, miso);

  input         rst;            // reset
  input         ss;             // slave select
  input         sclk;           // serial clock
  input         mosi;           // master out slave in
  output        miso;           // master in slave out

  reg           miso;

  reg           rx_negedge;     // slave receiving on negedge
  reg           tx_negedge;     // slave transmiting on negedge
  reg    [31:0] data;           // data register

  parameter     Tp = 1;

  always @(posedge(sclk && !rx_negedge) or negedge(sclk && rx_negedge) or rst)
  begin
    if (rst)
      data <= #Tp 32'b0;
    else if (!ss)
      data <= #Tp {data[30:0], mosi};
  end

  always @(posedge(sclk && !tx_negedge) or negedge(sclk && tx_negedge))
  begin
    miso <= #Tp data[31];
  end

endmodule
module chdr_32f_to_16s_tb();

  reg clk = 0;
  reg reset = 1;
  //generate clock
  always #10 clk = ~clk;

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



  //tells when to finish
  initial
    begin
      #50 reset = 0;
      #50000;
      $finish;
    end

   //setting registers and wire
  reg [63:0]  i_tdata;
  reg         i_tlast = 0;
  reg         i_tvalid = 0;
  wire        i_tready;

  wire [63:0] o_tdata;
  wire        o_tlast;

  wire        o_tvalid;
  reg         o_tready;

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

  chdr_32f_to_16s #(.BASE(89))dut
  (
    .clk(clk),
    .rst(reset),
    .set_data(set_data),
    .set_stb(set_stb),
    .set_addr(set_addr),
    .i_tdata(i_tdata),
    .i_tlast(i_tlast),
    .i_tvalid(i_tvalid),
    .i_tready(i_tready),
    .o_tdata(o_tdata),
    .o_tlast(o_tlast),
    .o_tvalid(o_tvalid),
    .o_tready(o_tready),
    .debug()
  );

  reg [31:0]data[0:7];
  initial $readmemh("iq_to_float_output.txt", data);


  task test_packet;
    input [15:0] len;
    input [31:0] sid;
    reg [4:0] index;
    begin
      index <= 0;
      @(posedge clk) ;
      //send header
      i_tdata <= {1'b0, 1'b0, 1'b1, 1'b0, 12'h0, (len + 16'd16), sid};
      i_tvalid <= 1;
      i_tlast <= 0;
      @(posedge clk);
      while (i_tready != 1)
        @(posedge clk);
          i_tdata <= {64'b0};

      @(posedge clk);
      while (i_tready != 1)
        @(posedge clk);
        //-1 for last bit accounting
        repeat (len[15:3] + (len[2]|len[1]|len[0]) - 1)
        begin
          i_tdata <= {data[index],data[index+1]};
          index <= index+2;
          @(posedge clk);
          while (i_tready != 1)
            @(posedge clk);
        end
        i_tlast <= 1'b1;
        i_tdata <= {data[index], data[index+1]};

        @(posedge clk);
        while (i_tready != 1)
          @(posedge clk);
          i_tvalid <= 0;
    end
  endtask // test_packet

  task test_destination;
    input enable;
    input [15:0] dest_home;

    begin
      @(posedge clk);

      set_data <= {enable,dest_home};
      set_addr <= 89;
      set_stb <= 1;

      @(posedge clk);
        set_stb <= 0;
    end
  endtask


  initial
    begin
      i_tvalid <= 0;
      o_tready <= 1;
      i_tdata <= 0;

      @(negedge reset);
      @(posedge clk);
      @(posedge clk);

      test_destination(1,16'hFEED);
      test_packet(4, 32'hDEAD_BEEF);

      test_destination(1,16'hFEED);
      test_packet(8, 32'hDEAD_BEEF);

      test_destination(1,16'hFEED);
      test_packet(16, 32'hDEAD_BEEF);

      test_destination(1,16'hFEED);
      test_packet(20, 32'hDEAD_BEEF);

      test_destination(1,16'hFEED);
      test_packet(24, 32'hDEAD_BEEF);

      test_destination(1,16'hFEED);
      test_packet(28, 32'hDEAD_BEEF);
  end
endmodule
module chdr_16s_to_32f_tb();
  reg clk = 0;
  reg rst = 1;
  //generate clock
  always #10 clk = ~clk;

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

   //tells when to finish
  initial
    begin
      #50 rst = 0;
      #50000;
      $finish;
    end

  //setting registers and wire
  reg [63:0]  i_tdata;
  reg         i_tlast = 0;
  reg         i_tvalid = 0;
  wire        i_tready;
  reg [7:0]   set_addr;
  reg [31:0]  set_data;
  reg         set_stb;


  wire [63:0] o_tdata;
  wire        o_tlast;

  wire        o_tvalid;
  reg         o_tready;

  chdr_16s_to_32f #(.BASE(89))dut
  (
    .clk(clk),
    .rst(rst),
    .set_data(set_data),
    .set_stb(set_stb),
    .set_addr(set_addr),
    .i_tdata(i_tdata),
    .i_tlast(i_tlast),
    .i_tvalid(i_tvalid),
    .i_tready(i_tready),
    .o_tdata(o_tdata),
    .o_tlast(o_tlast),
    .o_tvalid(o_tvalid),
    .o_tready(o_tready),
    .debug()
  );


  //change [15:0] to whatever amount of samples you want to test. however float to iq was tested thouroughly independently. so it works
  reg [15:0]data[0:15];
  initial $readmemh("chdr_16s_to_32f_input.txt", data);

  //test packet loop
  task test_packet;
    input [15:0] len;
    input [31:0] sid;
    reg [3:0] index;

    begin
      index <= 0;
      @(posedge clk);
        //send header
        i_tdata <= {1'b0, 1'b0, 1'b1, 1'b0, 12'h0, (len + 16'd16),sid};
        i_tvalid <= 1;
        i_tlast <= 0;

      @(posedge clk);
        while (i_tready != 1)
      @(posedge clk);
        i_tdata <= {64'b0};

      @(posedge clk);
        while (i_tready != 1)
      @(posedge clk);
        //-1 for last bit accounting
        repeat (len[15:3] + (len[2]|len[1]|len[0])-1)
        begin
          i_tdata <= {data[index], data[index+1], data[index+2], data[index+3]};
          index <= index+4;

          @(posedge clk);
            while (i_tready != 1)
          @(posedge clk);
        end
        i_tlast <= 1'b1;
        i_tdata <= {data[index], data[index+1], data[index+2], data[index+3]};


        @(posedge clk);
          while (i_tready != 1)
        @(posedge clk);
          i_tvalid <= 0;
    end
  endtask // test_packet

  //test_destination loop

  task test_destination;
    input enable;
    input [15:0] dest_home;


    begin
      @(posedge clk);

      set_data <= {enable,dest_home};
      set_addr <= 89;
      set_stb <= 1;

      @(posedge clk);
        set_stb <= 0;
    end
  endtask

  //main loop
  initial
    begin
      i_tvalid <= 0;
      o_tready <= 1;

      i_tdata <= 0;

      @(negedge rst);
      @(posedge clk);
      @(posedge clk);

      test_destination(1,16'hFEED);
      test_packet(2, 32'hDEAD_BEEF);

      test_destination(1,16'hFEED);
      test_packet(4, 32'hDEAD_BEEF);

      test_destination(1,16'hFEED);
      test_packet(6, 32'hDEAD_BEEF);

      test_destination(1,16'hFEED);
      test_packet(8, 32'hDEAD_BEEF);

    end

endmodule
module catgen_tb();

   wire GSR, GTS;
   glbl glbl( );

   reg 	clk    = 0;
   reg 	reset  = 1;
   wire ddrclk;
   
   always #100 clk = ~clk;

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

   wire [11:0] pins;
   wire        frame;
   
   reg 	       mimo;
   reg [7:0]   count;
   reg 	       tx_strobe;
   
   wire [11:0] i0 = {4'hA,count};
   wire [11:0] q0 = {4'hB,count};
   wire [11:0] i1 = {4'hC,count};
   wire [11:0] q1 = {4'hD,count};

   initial
     begin
	#1000 reset = 0;
	BURST(4);
	BURST(5);
	MIMO_BURST(4);
	MIMO_BURST(5);
	#2000;
	$finish;
     end
   
   task BURST;
      input [7:0] len;

      begin
	 tx_strobe <= 0;
	 mimo <= 0;
	 count <= 0;
	 @(posedge clk);
	 @(posedge clk);
	 repeat(len)
	   begin
	      tx_strobe <= 1;
	      @(posedge clk);
	      count <= count + 1;
	   end
	 tx_strobe <= 0;
	 @(posedge clk);
	 @(posedge clk);
	 @(posedge clk);
      end
   endtask // BURST
   
   task MIMO_BURST;
      input [7:0] len;

      begin
	 tx_strobe <= 0;
	 mimo <= 1;
	 count <= 0;
	 @(posedge clk);
	 @(posedge clk);
	 repeat(len)
	   begin
	      tx_strobe <= 1;
	      @(posedge clk);
	      tx_strobe <= 0;
	      @(posedge clk);
	      count <= count + 1;
	   end
	 tx_strobe <= 0;
	 @(posedge clk);
	 @(posedge clk);
	 @(posedge clk);
      end
   endtask // BURST
   
   catgen_ddr_cmos catgen
     (.data_clk(ddrclk),
      .reset(reset),
      .mimo(mimo),
      .tx_frame(frame),
      .tx_d(pins),
      .tx_clk(clk),
      .tx_strobe(tx_strobe),
      .i0(i0),.q0(q0),
      .i1(i1),.q1(q1));
   
endmodule // hb_chain_tb
module catcap_tb();

   wire GSR, GTS;
   glbl glbl( );

   reg 	clk    = 0;
   reg 	ddrclk = 0;
   reg 	reset  = 1;

   always #100 clk = ~clk;
   always @(negedge clk) ddrclk <= ~ddrclk;

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

   wire [11:0] i0 = {4'hA,count};
   wire [11:0] q0 = {4'hB,count};
   wire [11:0] i1 = {4'hC,count};
   wire [11:0] q1 = {4'hD,count};

   reg 	       mimo;
   reg [11:0]  pins;
   reg 	       frame;
   reg [7:0]   count;
   
   initial
     begin
	#1000 reset = 0;
	MIMO_BURST(4);
	MIMO_BURST(5);
	BURST(4);
	BURST(5);
	#2000;
	$finish;
     end
   
   task BURST;
      input [7:0] len;
      begin
	 frame <= 0;
	 @(posedge clk);
	 @(posedge clk);
	 mimo <= 0;
	 @(posedge clk);
	 @(posedge clk);
	 @(posedge clk);
	 @(posedge ddrclk);
	 count <= 0;
	 repeat(len)
	   begin
	      @(posedge clk);
	      pins <= i0;
	      frame <= 1;
	      @(posedge clk);
	      pins <= q0;
	      frame <= 0;
	      count <= count + 1;
	   end
      end
   endtask // BURST
   
   task MIMO_BURST;
      input [7:0] len;
      begin
	 frame <= 0;
	 @(posedge clk);
	 @(posedge clk);
	 mimo <= 1;
	 @(posedge clk);
	 @(posedge clk);
	 @(posedge clk);
	 @(posedge ddrclk);
	 count <= 0;
	 repeat(len)
	   begin
	      @(posedge clk);
	      pins <= i0;
	      frame <= 1;
	      @(posedge clk);
	      pins <= q0;
	      @(posedge clk);
	      pins <= i1;
	      frame <= 0;
	      @(posedge clk);
	      pins <= q1;
	      count <= count + 1;
	   end
	 @(posedge clk);
	 @(posedge clk);
      end
   endtask // MIMO_BURST
      
   wire        rx_clk, rx_strobe;
   wire [11:0] i0o,i1o,q0o,q1o;
   
   catcap_ddr_cmos catcap
     (.data_clk(ddrclk),
      .reset(reset),
      .mimo(mimo),
      .rx_frame(frame),
      .rx_d(pins),
      .rx_clk(rx_clk),
      .rx_strobe(rx_strobe),
      .i0(i0o),.q0(q0o),
      .i1(i1o),.q1(q1o));
   
endmodule // hb_chain_tb
module null_source_tb();
   
   reg clk, reset;
   always
     #100 clk = ~clk;

   initial clk = 0;
   initial reset = 1;
   initial #1000 reset = 0;
   
   initial $dumpfile("null_source_tb.vcd");
   initial $dumpvars(0,null_source_tb);

   //initial #10000000 $finish;

   reg [31:0] set_data;
   reg [7:0]  set_addr;
   reg        set_stb=0;

   wire [63:0] src_tdata;
   wire	       src_tlast, src_tvalid;
   wire        src_tready;

   assign src_tready = 1'b1;
   
   localparam PORTS = 4;

   null_source #(.BASE(0)) axi_wrapper_ce1
     (.clk(clk), .reset(reset),
      .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
      .o_tdata(src_tdata), .o_tlast(src_tlast), .o_tvalid(src_tvalid), .o_tready(src_tready)     );

   initial
     begin

	@(negedge reset);
	@(posedge clk);
	#100000;
	@(posedge clk);
	set_stb <= 1;
	set_addr <= 0;
	set_data <= 32'hDEADBEEF;
	@(posedge clk);
	set_stb <= 1;
	set_addr <= 1;  // Len
	set_data <= 32'h8;
	@(posedge clk);
	set_stb <= 1;
	set_addr <= 2;
	set_data <= 32'h20; // Rate
	@(posedge clk);
	set_stb <= 1;
	set_addr <= 3;
	set_data <= 1;     // enable
	@(posedge clk);
	set_stb <= 0;
	@(posedge clk);
	#1000000;
	@(posedge clk);
	set_stb <= 1;
	set_addr <= 3;
	set_data <= 0;     // disable
	@(posedge clk);
	set_stb <= 0;
	#1000000;

	$finish;
	
	
     end

endmodule // null_source_tb
module moving_sum_tb();
   
   //xlnx_glbl glbl (.GSR(),.GTS());
   
   localparam STR_SINK_FIFOSIZE = 9;
      
   reg clk, reset;
   always
     #100 clk = ~clk;

   initial clk = 0;
   initial reset = 1;
   initial #1000 reset = 0;
   
   initial $dumpfile("moving_sum_tb.vcd");
   initial $dumpvars(0,moving_sum_tb);

   initial #1000000 $finish;

   wire [15:0] i_tdata;
   wire [25:0] o_tdata;
   wire        i_tvalid, i_tready, o_tvalid, o_tready;
   
   moving_sum #(.MAX_LEN_LOG2(10), .WIDTH(16)) moving_sum
     (.clk(clk), .reset(reset), .clear(0),
      .len(20),
      .i_tdata(i_tdata), .i_tlast(), .i_tvalid(i_tvalid), .i_tready(i_tready),
      .o_tdata(o_tdata), .o_tlast(), .o_tvalid(o_tvalid), .o_tready(o_tready));

   assign i_tdata = 1;
   assign i_tvalid = 1;
   assign o_tready = 1;
   
      
endmodule // moving_sum_tb
module mult_add_tb();
   
   xlnx_glbl glbl (.GSR(),.GTS());
   
   localparam STR_SINK_FIFOSIZE = 9;
      
   reg clk, reset;
   always
     #100 clk = ~clk;

   initial clk = 0;
   initial reset = 1;
   initial #1000 reset = 0;
   
   initial $dumpfile("mult_add_tb.vcd");
   initial $dumpvars(0,mult_add_tb);

   initial #1000000 $finish;

   localparam AW=25;
   localparam BW=18;
   localparam PW=48;
   
   wire [AW-1:0] a_tdata;
   wire [BW-1:0] b_tdata;
   wire [PW-1:0] pin_tdata;
   wire [PW-1:0] pout_tdata;
   
   wire 	 a_tlast, a_tvalid, a_tready, b_tlast, b_tvalid, b_tready;
   wire 	 pin_tlast, pin_tvalid;
   wire 	 pout_tlast, pout_tvalid;
   wire 	 pin_tready;
   reg 		 pout_tready = 0;

   reg 		 ai_tvalid = 0;
   reg 		 bi_tvalid = 0;
   reg 		 pi_tvalid = 0;
   
   counter #(.WIDTH(AW)) ca
     (.clk(clk), .reset(reset), .clear(0),
      .max(25'd20),
      .i_tlast(0), .i_tvalid(ai_tvalid), .i_tready(),
      .o_tdata(a_tdata), .o_tlast(a_tlast), .o_tvalid(a_tvalid), .o_tready(a_tready));
   
   counter #(.WIDTH(BW)) cb
     (.clk(clk), .reset(reset), .clear(0),
      .max(18'd20),
      .i_tlast(0), .i_tvalid(bi_tvalid), .i_tready(),
      .o_tdata(b_tdata), .o_tlast(b_tlast), .o_tvalid(b_tvalid), .o_tready(b_tready));
   
   counter #(.WIDTH(PW)) cp
     (.clk(clk), .reset(reset), .clear(0),
      .max(48'd20),
      .i_tlast(0), .i_tvalid(pi_tvalid), .i_tready(),
      .o_tdata(pin_tdata), .o_tlast(pin_tlast), .o_tvalid(pin_tvalid), .o_tready(pin_tready));
   
   mult_add #(.WIDTH_A(AW), .WIDTH_B(BW), .WIDTH_P(PW),
	      .LATENCY(3), .CASCADE_IN(1), .CASCADE_OUT(1)) mult_add
     (.clk(clk), .reset(reset),
      .a_tdata(a_tdata), .a_tlast(a_tlast), .a_tvalid(a_tvalid), .a_tready(a_tready),
      .b_tdata(b_tdata), .b_tlast(b_tlast), .b_tvalid(b_tvalid), .b_tready(b_tready),
      .c_tdata(pin_tdata), .c_tlast(pin_tlast), .c_tvalid(pin_tvalid), .c_tready(pin_tready),
      .p_tdata(pout_tdata), .p_tlast(pout_tlast), .p_tvalid(pout_tvalid), .p_tready(pout_tready));

   initial
     begin
	@(negedge reset);
	repeat (100)
	  @(posedge clk);
	ai_tvalid <= 1;
	repeat (10)
	  @(posedge clk);
	bi_tvalid <= 1;
	repeat (10)
	  @(posedge clk);
	pi_tvalid <= 1;
	repeat (10)
	  @(posedge clk);
	pout_tready <= 1;
     end
      
endmodule // mult_add_tb
module chdr_deframer_tb();
   
   reg clk, reset;
   always
     #100 clk = ~clk;

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

   reg [63:0] i_tdata;
   reg i_tlast, i_tvalid;
   wire i_tready;

   wire [31:0] o_tdata;
   wire [127:0] o_tuser;
   wire        o_tlast, o_tvalid;

   reg 	       o_tready = 1;

   wire [63:0] int_tdata;
   wire        int_tlast, int_tvalid, int_tready;
   
   axi_fifo #(.SIZE(10), .WIDTH(65)) fifo
     (.clk(clk), .reset(reset), .clear(0),
      .i_tdata({i_tlast, i_tdata}), .i_tvalid(i_tvalid), .i_tready(i_tready),
      .o_tdata({int_tlast, int_tdata}), .o_tvalid(int_tvalid), .o_tready(int_tready));
   
   chdr_deframer chdr_deframer
     (.clk(clk), .reset(reset), .clear(0),
      .i_tdata(int_tdata), .i_tlast(int_tlast), .i_tvalid(int_tvalid), .i_tready(int_tready),
      .o_tdata(o_tdata), .o_tuser(o_tuser), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready));

   reg [63:0]  hdr, vtime, data;
   
   initial
     begin
	clk = 0;
	reset = 1;
	i_tlast = 0;
	i_tvalid = 0;
	hdr = 64'hFF00_AAB9_BEEF_0000;
	vtime = 64'h8888_7777_6666_0000;
	data = 64'hEEEE_0000_FFFF_0001;
	#1000 reset = 0;
	repeat (10)
	  @(posedge clk);
	repeat (6)
	  begin
	     #1 i_tdata = hdr;
	     #1 i_tlast = 0;
	     #1 i_tvalid = 1;
	     @(posedge clk);
	     #1 i_tdata = vtime;
	     @(posedge clk);
	     #1 hdr = hdr + 1;
	     #1 vtime = vtime + 1;
	     repeat (10)
	       begin
		  #1 i_tdata = data;
		  #1 data = data + 64'h0000_0002_0000_0002;
		  @(posedge clk);
	       end
	     #1 i_tdata = data;
	     #1 data = data + 64'h0000_0002_0000_0002;
	     #1 i_tlast <= 1;
	     @(posedge clk);
	  end // repeat (20)
	#1 i_tvalid <= 0;
	#200000 $finish;
     end

   always @(posedge clk)
     if(o_tvalid & o_tready)
       if(o_tlast)
	 $display("%x    LAST",o_tdata);
       else
	 $display("%x",o_tdata);
   
endmodule // chdr_deframer_tb
module chdr_framer_tb();
   
   reg clk, reset;
   always
     #100 clk = ~clk;

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

   reg [31:0] i_tdata;
   reg [127:0] i_tuser;
   reg i_tlast, i_tvalid;
   wire i_tready;

   wire [63:0] o_tdata;
   wire        o_tlast, o_tvalid;

   reg 	       o_tready = 0;
   
   chdr_framer #(.SIZE(10)) chdr_framer
     (.clk(clk), .reset(reset), .clear(0),
      .i_tdata(i_tdata), .i_tuser(i_tuser), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
      .o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready));

   always 
     begin
	#1 o_tready = 1;
	repeat (200)
	  @(posedge clk);
	#1 o_tready = 0;
	repeat (120)
	  @(posedge clk);
     end
		   
	    
   initial
     begin
	clk = 0;
	reset = 1;
	i_tlast = 0;
	i_tvalid = 0;
	i_tdata = 32'hBEEF_0000;
	i_tuser = 128'hF123_4567_89ab_cdef_0011_2233_4455_0000;
	#1000 reset = 0;
	repeat (10)
	  @(posedge clk);
	#1 i_tvalid = 1;
	repeat (400)
	  begin
	     #1 i_tlast = 0;
	     repeat (22)
	       begin
		  #1 i_tdata = i_tdata + 1;
		  @(posedge clk);
	       end
	     #1 i_tdata = i_tdata + 1;
	     #1 i_tlast = 1;
	     @(posedge clk);
	     #1 i_tuser <= i_tuser + 1;
	  end // repeat (20)
	#1 i_tvalid <= 0;
	#100000 $finish;
     end

   always @(posedge clk)
     if(o_tvalid & o_tready)
       if(o_tlast)
	 $display("%x    LAST",o_tdata);
       else
	 $display("%x",o_tdata);
   
endmodule // chdr_framer_tb
module mult_tb();
   
   xlnx_glbl glbl (.GSR(),.GTS());
   
   localparam STR_SINK_FIFOSIZE = 9;
      
   reg clk, reset;
   always
     #100 clk = ~clk;

   initial clk = 0;
   initial reset = 1;
   initial #1000 reset = 0;
   
   initial $dumpfile("mult_tb.vcd");
   initial $dumpvars(0,mult_tb);

   initial #1000000 $finish;

   localparam AW=25;
   localparam BW=18;
   localparam PW=48;
   
   wire [AW-1:0] a_tdata;
   wire [BW-1:0] b_tdata;
   wire [PW-1:0] p_tdata;
   
   wire 	 a_tlast, a_tvalid, a_tready, b_tlast, b_tvalid, b_tready;
   wire 	 p_tlast, p_tvalid;
   reg 		 p_tready = 0;

   reg 		 ai_tvalid = 0;
   reg 		 bi_tvalid = 0;
   
   counter #(.WIDTH(AW)) ca
     (.clk(clk), .reset(reset), .clear(0),
      .max(20),
      .i_tlast(0), .i_tvalid(ai_tvalid), .i_tready(),
      .o_tdata(a_tdata), .o_tlast(a_tlast), .o_tvalid(a_tvalid), .o_tready(a_tready));
   
   counter #(.WIDTH(BW)) cb
     (.clk(clk), .reset(reset), .clear(0),
      .max(20),
      .i_tlast(0), .i_tvalid(bi_tvalid), .i_tready(),
      .o_tdata(b_tdata), .o_tlast(b_tlast), .o_tvalid(b_tvalid), .o_tready(b_tready));
   
   mult #(.WIDTH_A(AW), .WIDTH_B(BW), .WIDTH_P(PW), .LATENCY(4)) mult
     (.clk(clk), .reset(reset),
      .a_tdata(a_tdata), .a_tlast(a_tlast), .a_tvalid(a_tvalid), .a_tready(a_tready),
      .b_tdata(b_tdata), .b_tlast(b_tlast), .b_tvalid(b_tvalid), .b_tready(b_tready),
      .p_tdata(p_tdata), .p_tlast(p_tlast), .p_tvalid(p_tvalid), .p_tready(p_tready));

   initial
     begin
	@(negedge reset);
	repeat (100)
	  @(posedge clk);
	ai_tvalid <= 1;
	repeat (10)
	  @(posedge clk);
	bi_tvalid <= 1;
	repeat (10)
	  @(posedge clk);
	p_tready <= 1;
     end
      
endmodule // mult_tb
module axi_pipe_tb;

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

   reg clk = 0;
   always #100 clk <= ~clk;
   reg reset = 1;
   initial #1000 @(posedge clk) reset <= 1'b0;
   initial #30000 $finish;
   
   localparam LEN=10;
   wire [LEN-1:0] enables, valids;

   wire 	  o_tlast, i_tready, o_tvalid;
   reg 		  i_tvalid = 0;
   reg 		  o_tready = 0;
   reg 		  i_tlast = 0;
   
   axi_pipe #(.STAGES(LEN)) axi_pipe
     (.clk(clk), .reset(reset), .clear(0),
      .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
      .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready),
      .enables(enables), .valids(valids));

   initial
     begin
	@(negedge reset);
	repeat (3)
	  @(posedge clk);
	i_tvalid <= 1;
	@(posedge clk);
	i_tvalid <= 0;
	repeat (15) @(posedge clk);
	@(posedge clk);
	o_tready <= 1;
	repeat (15) @(posedge clk);
	o_tready <= 0;
	i_tvalid <= 1;
	repeat (15) @(posedge clk);
	o_tready <= 1;
	i_tvalid <= 0;
	repeat (15) @(posedge clk);
	o_tready <= 0;
	i_tvalid <= 1;
	@(posedge clk);
	i_tvalid <= 0;
	@(posedge clk);
	i_tvalid <= 1;
	@(posedge clk);
	@(posedge clk);
	i_tlast <= 1;
	@(posedge clk);
	i_tvalid <= 0;
	@(posedge clk);
	@(posedge clk);
	@(posedge clk);
	@(posedge clk);
	@(posedge clk);
	@(posedge clk);
	@(posedge clk);
	@(posedge clk);
	o_tready <= 1;

     end
   
endmodule // axi_pipe
module ddc_chain_x300_tb();
   
`ifdef ISIM
`else //iverilog implied.
//   xlnx_glbl glbl (.GSR(),.GTS());
`endif
   
   localparam SR_TX_DSP        = 8;

   reg clk    = 0;
   reg reset  = 1;
   
   always #10 clk = ~clk;
   
   initial $dumpfile("ddc_chain_x300_tb.vcd");
   initial $dumpvars(0,ddc_chain_x300_tb);
   reg run = 0;
   wire strobe;
   
   initial
     begin
	#1000 reset = 0;
	@(posedge clk);
	set_addr <= 0; set_data <= 32'd8434349; set_stb <= 1; @(posedge clk); // CORDIC
	set_addr <= 1; set_data <= 18'd19800; set_stb <= 1; @(posedge clk); // Scale factor
	set_addr <= 2; set_data <= 10'h003; set_stb <= 1; @(posedge clk); // Decim control
	set_addr <= 3; set_data <= 0; set_stb <= 1; @(posedge clk); // Swap iq
	set_addr <= 4; set_data <= 0; set_stb <= 1; @(posedge clk); // filter taps
	set_stb <= 0;
		
	repeat(10)
	  @(posedge clk);
	run <= 1'b1;
	#30000;
	$finish;
     end
   
   reg [7:0]   set_addr;
   reg [31:0]  set_data;
   reg 	       set_stb = 1'b0;

   wire [15:0] i_out, q_out;
   wire [23:0] rx_fe_i, rx_fe_q;

   assign rx_fe_i = 24'd8388607;
   assign rx_fe_q = 24'd8388607;
   //assign rx_fe_q = 0;
   
   ddc_chain_x300 #(.BASE(0), .DSPNO(0), .WIDTH(24)) ddc_chain
     (.clk(clk), .rst(reset), .clr(1'b0),
      .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
      .rx_fe_i(rx_fe_i),.rx_fe_q(rx_fe_q),
      .sample({i_out,q_out}), .run(run), .strobe(strobe),
      .debug() );
   
endmodule // new_tx_tb
module axi_packet_gate_tb();

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

   task send_packet;
      input [63:0] data_start;
      input [2:0]  user;
      input [31:0] len;
      input 	   error;
      
      begin
	 // Send a packet
	 @(posedge clk);
	 {i_terror, i_tuser, i_tlast, i_tdata} <= { 1'b0, user, 1'b0, data_start };
	 repeat(len-1)
	   begin
	      i_tvalid <= 1;
	      @(posedge clk);
	      i_tdata <= i_tdata + 1;
	   end
	 i_tlast <= 1;
	 i_terror <= error;
	 i_tdata <= i_tdata + 1;
	 @(posedge clk);
	 i_tvalid <= 1'b0;
	 
	 @(posedge clk);
      end
   endtask // send_packet
   
   
   initial
     begin
	#1000 reset = 0;
	#200000;
	$finish;
     end
   
   wire [63:0]  o_tdata;
   reg [63:0] 	i_tdata;
   wire [2:0] 	o_tuser;
   reg [2:0] 	i_tuser;
   reg 		i_tlast;
   wire 	o_tlast;
   wire		o_tvalid, i_tready;
   reg 		i_tvalid, o_tready;
   reg 		i_terror;
   
   localparam RPT_COUNT = 16;
   
   initial
     begin
	i_tvalid <= 0;
	o_tready <= 0;
	
	while(reset)
	  @(posedge clk);
	@(posedge clk);

	send_packet(64'hA0,3'd0, 16, 0);
	send_packet(64'hB0,3'd0, 16, 0);
	o_tready <= 1;
	send_packet(64'hC0,3'd0, 16, 1);
	send_packet(64'hD0,3'd0, 16, 0);
	send_packet(64'hE0,3'd0, 16, 0);
	send_packet(64'hF0,3'd0, 16, 0);

	@(posedge clk);

     end // initial begin

   wire i_terror_int, i_tlast_int, i_tready_int, i_tvalid_int;
   wire [2:0] i_tuser_int;
   wire [63:0] i_tdata_int;
   wire o_tlast_int, o_tready_int, o_tvalid_int;
   wire [2:0] o_tuser_int;
   wire [63:0] o_tdata_int;
   
   axi_fifo #(.WIDTH(69), .SIZE(10)) fifo
     (.clk(clk), .reset(reset), .clear(1'b0),
      .i_tdata({i_terror,i_tlast,i_tuser,i_tdata}), .i_tvalid(i_tvalid), .i_tready(i_tready),
      .o_tdata({i_terror_int,i_tlast_int,i_tuser_int,i_tdata_int}), .o_tvalid(i_tvalid_int), .o_tready(i_tready_int));

   axi_packet_gate #(.WIDTH(67), .SIZE(10)) dut
     (.clk(clk), .reset(reset), .clear(1'b0),
      .i_tdata({i_tuser_int,i_tdata_int}), .i_terror(i_terror_int), .i_tlast(i_tlast_int), .i_tvalid(i_tvalid_int), .i_tready(i_tready_int),
      .o_tdata({o_tuser_int,o_tdata_int}), .o_tlast(o_tlast_int), .o_tvalid(o_tvalid_int), .o_tready(o_tready_int));

   axi_fifo #(.WIDTH(68), .SIZE(10)) fifo_out
     (.clk(clk), .reset(reset), .clear(1'b0),
      .i_tdata({o_tlast_int,o_tuser_int,o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int),
      .o_tdata({o_tlast,o_tuser,o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready));

   always @(posedge clk)
     if(o_tvalid & o_tready)
       $display("TUSER %x\tTLAST %x\tTDATA %x",o_tuser,o_tlast, o_tdata);

endmodule // axi_packet_gate_tb
module rx_dsp_model
  (input clk, input reset,
   input run,
   input [7:0] decim,
   output strobe,
   output [31:0] sample);
   
   reg [15:0] 	  pktnum = 0;
   reg [15:0] 	 counter = 0;

   reg 		 run_d1;
   always @(posedge clk) run_d1 <= run;
   
   always @(posedge clk)
     if(run & ~run_d1)
       begin
	  counter 		<= 0;
	  pktnum 		<= pktnum + 1;
       end
     else if(run & strobe)
       counter 			<= counter + 1;
       
   assign sample 		 = {pktnum,counter};

   reg [7:0] stb_ctr = 0;
   
   always @(posedge clk)
     if(reset)
       stb_ctr 	 <= 0;
     else if(run & ~run_d1)
       stb_ctr 	 <= 1;
     else if(run)
       if(stb_ctr == decim-1)
	 stb_ctr <= 0;
       else
	 stb_ctr <= stb_ctr + 1;

   assign strobe  = stb_ctr == decim-1;
   
endmodule // rx_dsp_model
module tx_dsp_model
  (input clk, input reset,
   input run,
   input [7:0] interp,
   output strobe,
   input [31:0] sample);

   cic_strober strober(.clock(clk), .reset(reset), .enable(run), .rate(interp), .strobe_fast(1), .strobe_slow(strobe));

   always @(posedge clk)
     if(strobe)
       $display("Time %d, Sent Sample %x",$time,sample);
   
   
endmodule // tx_dsp_model