dakies/OSS_Verilog huggingface dataset:
module generic_mem_medium(
 
    wclk,
    wrst_n,
    wen,
    waddr,
    wdata,
 
    rclk,
    rrst_n,
    ren,
    roen,
    raddr,
    rdata
);
 
//---
// Parameters
 
parameter DWIDTH = 32;
parameter AWIDTH = 3;
parameter RAM_DEPTH = (1 << AWIDTH);
parameter SYNC_WRITE = 1;
parameter SYNC_READ = 1;
parameter REGISTER_READ = 0;
 
//---
// Ports
 
input               wclk;
input               wrst_n;
input               wen;
input  [AWIDTH:0]   waddr;
input  [DWIDTH-1:0] wdata;
 
input               rclk;
input               rrst_n;
input               ren;
input               roen;
input  [AWIDTH:0]   raddr;
output [DWIDTH-1:0] rdata;
 
// Registered outputs
reg    [DWIDTH-1:0] rdata;
 
 
//---
// Local declarations
 
// Registers
 
reg  [DWIDTH-1:0] mem_rdata;
 
 
// Memory - infer using Xilinx pragma for block ram.
//synthesis attribute ram_style of mem is block
reg  [DWIDTH-1:0] mem [0:RAM_DEPTH-1];
 
// Variables
 
integer         i;
 
 
//---
// Memory Write
 
generate
    if (SYNC_WRITE) begin
 
        // Generate synchronous write
        always @(posedge wclk)
        begin
            if (wen) begin
                mem[waddr[AWIDTH-1:0]] <= wdata;
            end
        end
    end
    else begin
 
        // Generate asynchronous write
        always @(wen, waddr, wdata)
        begin
            if (wen) begin
                mem[waddr[AWIDTH-1:0]] = wdata;
            end
        end
    end
endgenerate
 
//---
// Memory Read
 
generate
    if (SYNC_READ) begin
 
        // Generate registered memory read
        always @(posedge rclk /* IJB  or negedge rrst_n*/)
        begin
            if (!rrst_n) begin
                mem_rdata <= {(DWIDTH){1'b0}};
            end else if (ren) begin
                mem_rdata <= mem[raddr[AWIDTH-1:0]];
            end
        end
    end
    else begin
 
        // Generate unregisters memory read
        always @(raddr, rclk)
        begin
            mem_rdata = mem[raddr[AWIDTH-1:0]];
        end
    end
endgenerate
 
generate
    if (REGISTER_READ) begin
 
        // Generate registered output
        always @(posedge rclk /* IJB or negedge rrst_n*/ )
        begin
            if (!rrst_n) begin
                rdata <= {(DWIDTH){1'b0}};
            end else if (roen) begin
                rdata <= mem_rdata;
            end
        end
 
    end
    else begin
 
        // Generate unregisters output
        always @(mem_rdata)
        begin
            rdata = mem_rdata;
        end
 
    end
endgenerate
 
endmodule
module meta_sync(/*AUTOARG*/
  // Outputs
  out,
  // Inputs
  clk, reset_n, in
  );
 
parameter DWIDTH = 1;
parameter EDGE_DETECT = 0;
 
input                clk;
input                reset_n;
 
input  [DWIDTH-1:0]  in;
 
output [DWIDTH-1:0]  out;
 
generate
genvar               i;
 
    for (i = 0; i < DWIDTH; i = i + 1) begin : meta
 
        meta_sync_single #(.EDGE_DETECT (EDGE_DETECT))
          meta_sync_single0 (
                      // Outputs
                      .out              (out[i]),
                      // Inputs
                      .clk              (clk),
                      .reset_n          (reset_n),
                      .in               (in[i]));
 
    end
 
endgenerate
 
endmodule
module sync_clk_core(/*AUTOARG*/
  // Inputs
  clk_xgmii_tx, reset_xgmii_tx_n
  );
 
input         clk_xgmii_tx;
input         reset_xgmii_tx_n;
 
//input         ctrl_tx_disable_padding;
 
//output        ctrl_tx_disable_padding_ccr;
 
 
/*AUTOREG*/
 
/*AUTOWIRE*/
 
//wire  [0:0]             sig_out;
 
//assign {ctrl_tx_disable_padding_ccr} = sig_out;
 
//meta_sync #(.DWIDTH (1)) meta_sync0 (
//                      // Outputs
//                      .out              (sig_out),
//                      // Inputs
//                      .clk              (clk_xgmii_tx),
//                      .reset_n          (reset_xgmii_tx_n),
//                      .in               ({
//                                          ctrl_tx_disable_padding
//                                         }));
 
endmodule
module tx_data_fifo(/*AUTOARG*/
  // Outputs
  txdfifo_wfull, txdfifo_walmost_full, txdfifo_rdata, txdfifo_rstatus,
  txdfifo_rempty, txdfifo_ralmost_empty,
  // Inputs
  clk_xgmii_tx, clk_156m25, reset_xgmii_tx_n, reset_156m25_n,
  txdfifo_wdata, txdfifo_wstatus, txdfifo_wen, txdfifo_ren
  );
 
input         clk_xgmii_tx;
input         clk_156m25;
input         reset_xgmii_tx_n;
input         reset_156m25_n;
 
input [63:0]  txdfifo_wdata;
input [7:0]   txdfifo_wstatus;
input         txdfifo_wen;
 
input         txdfifo_ren;
 
output        txdfifo_wfull;
output        txdfifo_walmost_full;
 
output [63:0] txdfifo_rdata;
output [7:0]  txdfifo_rstatus;
output        txdfifo_rempty;
output        txdfifo_ralmost_empty;
 
generic_fifo #(
  .DWIDTH (72),
  .AWIDTH (`TX_DATA_FIFO_AWIDTH),
  .REGISTER_READ (1),
  .EARLY_READ (1),
  .CLOCK_CROSSING (1),
  .ALMOST_EMPTY_THRESH (7),
  .ALMOST_FULL_THRESH (12),
  .MEM_TYPE (`MEM_AUTO_XILINX)
)
fifo0(
    .wclk (clk_156m25),
    .wrst_n (reset_156m25_n),
    .wen (txdfifo_wen),
    .wdata ({txdfifo_wstatus, txdfifo_wdata}),
    .wfull (txdfifo_wfull),
    .walmost_full (txdfifo_walmost_full),
 
    .rclk (clk_xgmii_tx),
    .rrst_n (reset_xgmii_tx_n),
    .ren (txdfifo_ren),
    .rdata ({txdfifo_rstatus, txdfifo_rdata}),
    .rempty (txdfifo_rempty),
    .ralmost_empty (txdfifo_ralmost_empty)
);
 
endmodule
module meta_sync_single(/*AUTOARG*/
  // Outputs
  out,
  // Inputs
  clk, reset_n, in
  );
 
parameter EDGE_DETECT = 0;
 
input   clk;
input   reset_n;
 
input   in;
 
output  out;
 
reg     out;
 
 
 
generate
 
    if (EDGE_DETECT) begin
 
      reg   meta;
      reg   edg1;
      reg   edg2;
 
        always @(posedge clk or negedge reset_n) begin
 
            if (reset_n == 1'b0) begin
                meta <= 1'b0;
                edg1 <= 1'b0;
                edg2 <= 1'b0;
                out <= 1'b0;
            end
            else begin
                meta <= in;
                edg1 <= meta;
                edg2 <= edg1;
                out <= edg1 ^ edg2;
            end
        end
 
    end
    else begin
 
      reg   meta;
 
        always @(posedge clk or negedge reset_n) begin
 
            if (reset_n == 1'b0) begin
                meta <= 1'b0;
                out <= 1'b0;
            end
            else begin
                meta <= in;
                out <= meta;
            end
        end
 
    end
 
endgenerate
 
endmodule
module rx_data_fifo(/*AUTOARG*/
  // Outputs
  rxdfifo_wfull, rxdfifo_rdata, rxdfifo_rstatus, rxdfifo_rempty,
  rxdfifo_ralmost_empty,
  // Inputs
  clk_xgmii_rx, clk_156m25, reset_xgmii_rx_n, reset_156m25_n,
  rxdfifo_wdata, rxdfifo_wstatus, rxdfifo_wen, rxdfifo_ren
  );
 
input         clk_xgmii_rx;
input         clk_156m25;
input         reset_xgmii_rx_n;
input         reset_156m25_n;
 
input [63:0]  rxdfifo_wdata;
input [7:0]   rxdfifo_wstatus;
input         rxdfifo_wen;
 
input         rxdfifo_ren;
 
output        rxdfifo_wfull;
 
output [63:0] rxdfifo_rdata;
output [7:0]  rxdfifo_rstatus;
output        rxdfifo_rempty;
output        rxdfifo_ralmost_empty;
 
generic_fifo #(
  .DWIDTH (72),
  .AWIDTH (`RX_DATA_FIFO_AWIDTH),
  .REGISTER_READ (0),
  .EARLY_READ (1),
  .CLOCK_CROSSING (1),
  .ALMOST_EMPTY_THRESH (4),
  .MEM_TYPE (`MEM_AUTO_XILINX)
)
fifo0(
    .wclk (clk_xgmii_rx),
    .wrst_n (reset_xgmii_rx_n),
    .wen (rxdfifo_wen),
    .wdata ({rxdfifo_wstatus, rxdfifo_wdata}),
    .wfull (rxdfifo_wfull),
    .walmost_full (),
 
    .rclk (clk_156m25),
    .rrst_n (reset_156m25_n),
    .ren (rxdfifo_ren),
    .rdata ({rxdfifo_rstatus, rxdfifo_rdata}),
    .rempty (rxdfifo_rempty),
    .ralmost_empty (rxdfifo_ralmost_empty)
);
 
 
endmodule
module f15_avg #(
	parameter integer Y_WIDTH = 12,
	parameter integer X_WIDTH = 16
)(
	input  wire [Y_WIDTH-1:0] yin_0,
	input  wire [X_WIDTH-1:0] x_0,
	input  wire [15:0] rng_0,
	input  wire [15:0] alpha_0,
	input  wire clear_0,
	output wire [Y_WIDTH-1:0] yout_4,
	input  wire clk,
	input  wire rst
);

	// Signals
	wire [X_WIDTH-1:0] x_2;
	wire clear_3;
	wire [47:0] pout_4;

	// Main DSP Instance
	DSP48E1 #(
		.A_INPUT("DIRECT"),
		.B_INPUT("DIRECT"),
		.USE_DPORT("TRUE"),
		.USE_MULT("MULTIPLY"),
		.AUTORESET_PATDET("NO_RESET"),
		.MASK(48'h3fffffffffff),
		.PATTERN(48'h000000000000),
		.SEL_MASK("MASK"),
		.SEL_PATTERN("PATTERN"),
		.USE_PATTERN_DETECT("PATDET"),
		.ACASCREG(1),
		.ADREG(1),
		.ALUMODEREG(1),
		.AREG(1),
		.BCASCREG(1),
		.BREG(2),
		.CARRYINREG(1),
		.CARRYINSELREG(1),
		.CREG(1),
		.DREG(1),
		.INMODEREG(1),
		.MREG(1),
		.OPMODEREG(1),
		.PREG(1),
		.USE_SIMD("ONE48")
	)
	dsp_avg_I (
		.P(pout_4),
		.ACIN(30'h0),
		.BCIN(18'h0),
		.CARRYCASCIN(1'h0),
		.MULTSIGNIN(1'h0),
		.PCIN(48'h000000000000),
		.ALUMODE(4'b0000),		// Z + X + Y + CIN
		.CARRYINSEL(3'h0),
		.CEINMODE(1'b1),
		.CLK(clk),
		.INMODE(5'b01100),		// B=B2, A=D-A2
		.OPMODE(7'b0110101),	// X=M1, Y=M2, Z=C
		.RSTINMODE(rst),
		.A({{(30-X_WIDTH){1'b0}}, x_0}),
		.B({2'h0, alpha_0}),
		.C({{(32-X_WIDTH){1'b0}}, x_2, 16'h8000}),
		.CARRYIN(1'b0),
		.D({{(25-X_WIDTH){1'b0}}, yin_0, rng_0[X_WIDTH-Y_WIDTH-1:0]}),
		.CEA1(1'b0),
		.CEA2(1'b1),
		.CEAD(1'b1),
		.CEALUMODE(1'b1),
		.CEB1(1'b1),
		.CEB2(1'b1),
		.CEC(1'b1),
		.CECARRYIN(1'b1),
		.CECTRL(1'b1),
		.CED(1'b1),
		.CEM(1'b1),
		.CEP(1'b1),
		.RSTA(rst),
		.RSTALLCARRYIN(rst),
		.RSTALUMODE(rst),
		.RSTB(rst),
		.RSTC(rst),
		.RSTCTRL(rst),
		.RSTD(rst),
		.RSTM(rst),
		.RSTP(clear_3)
	);

	// Delay x for the C input
	delay_bus #(2, X_WIDTH) dl_x (x_0, x_2, clk);

	// Delay clear to use as reset for P
	delay_bit #(3) dl_clear (clear_0, clear_3, clk);

	// Map the output
	assign yout_4 = pout_4[X_WIDTH+15:X_WIDTH-Y_WIDTH+16];

endmodule // f15_avg
module f15_rise_decay #(
	parameter integer WIDTH = 9
)(
	input  wire [WIDTH-1:0] in_0,	// input
	output reg  [WIDTH-1:0] out_5,	// output
	input  wire [15:0] k_0,			// time constant
	input  wire ena_0,				// If ena=0, then output original value
	input  wire mode_0,				// 0=rise, 1=decay
	input  wire [15:0] rng,
	input  wire clk,
	input  wire rst
);

	// Signals
	reg mode_1;
	reg [4:0] inmode_1;

	wire [WIDTH-1:0] in_2;
	wire ena_2;
	wire [6:0] opmode_2;
	reg  [3:0] alumode_2;

	wire [47:0] pout_4;
	wire pmatch_4;


	// Main DSP
	// --------

	// Mode control
		// For rise  we have INMODE=00000 (A=A2,   B=B2), ALUMODE=0000 (C+M)
		// For decay we have INMODE=01100 (A=D-A2, B=B2), ALUMODE=0011 (C-M)
	always @(posedge clk)
	begin
		mode_1 <= mode_0;

		if (mode_0)
			inmode_1 <= 5'b00000;
		else
			inmode_1 <= 5'b01100;

		if (mode_1)
			alumode_2 <= 4'b0011;
		else
			alumode_2 <= 4'b0000;
	end

		// When not enabled, we use OPMODE to do pass-through
	delay_bit #(2) dl_ena (ena_0, ena_2, clk);
	assign opmode_2  = ena_2 ? 7'b0110101 : 7'b0110000;

	// Delay for input to C
	delay_bus #(2, WIDTH) dl_in (in_0, in_2, clk);

	// Instance
	DSP48E1 #(
		.A_INPUT("DIRECT"),
		.B_INPUT("DIRECT"),
		.USE_DPORT("TRUE"),
		.USE_MULT("MULTIPLY"),
		.AUTORESET_PATDET("NO_RESET"),
		.MASK({1'b1, {(31-WIDTH){1'b0}}, {(WIDTH+16){1'b1}}}),
		.PATTERN(48'h000000000000),
		.SEL_MASK("MASK"),
		.SEL_PATTERN("PATTERN"),
		.USE_PATTERN_DETECT("PATDET"),
		.ACASCREG(1),
		.ADREG(1),
		.ALUMODEREG(1),
		.AREG(1),
		.BCASCREG(2),
		.BREG(2),
		.CARRYINREG(1),
		.CARRYINSELREG(1),
		.CREG(1),
		.DREG(1),
		.INMODEREG(1),
		.MREG(1),
		.OPMODEREG(1),
		.PREG(1),
		.USE_SIMD("ONE48")
	)
	dsp_exp_I (
		.PATTERNDETECT(pmatch_4),
		.P(pout_4),
		.ACIN(30'h0),
		.BCIN(18'h0),
		.CARRYCASCIN(1'h0),
		.MULTSIGNIN(1'h0),
		.PCIN(48'h000000000000),
		.ALUMODE(alumode_2),
		.CARRYINSEL(3'h0),
		.CEINMODE(1'b1),
		.CLK(clk),
		.INMODE(inmode_1),
		.OPMODE(opmode_2),
		.RSTINMODE(rst),
		.A({{(30-WIDTH){1'b0}}, in_0}),
		.B({ 2'h0, k_0}),
		.C({{(32-WIDTH){1'b0}}, in_2, rng}),
		.CARRYIN(1'b0),
		.D({{(24-WIDTH){1'b0}}, 1'b1, {WIDTH{1'b0}}}),
		.CEA1(1'b0),
		.CEA2(1'b1),
		.CEAD(1'b1),
		.CEALUMODE(1'b1),
		.CEB1(1'b1),
		.CEB2(1'b1),
		.CEC(1'b1),
		.CECARRYIN(1'b1),
		.CECTRL(1'b1),
		.CED(1'b1),
		.CEM(1'b1),
		.CEP(1'b1),
		.RSTA(rst),
		.RSTALLCARRYIN(rst),
		.RSTALUMODE(rst),
		.RSTB(rst),
		.RSTC(rst),
		.RSTCTRL(rst),
		.RSTD(rst),
		.RSTM(rst),
		.RSTP(rst)
	);


	// Saturation
	// ----------

	always @(posedge clk)
	begin
		if (rst == 1)
			out_5 <= 0;
		else
			if (pout_4[47] == 1)
				out_5 <= {WIDTH{1'b0}};
			else if (pmatch_4 == 0)
				out_5 <= {WIDTH{1'b1}};
			else
				out_5 <= pout_4[WIDTH+15:16];
	end

endmodule // f15_rise_decay
module f15_line_mem #(
	parameter integer AWIDTH = 12,
    parameter integer DWIDTH = 18
)(
	input  wire [AWIDTH-1:0] rd_addr,
	output reg  [DWIDTH-1:0] rd_data,
	input  wire rd_ena,

	input  wire [AWIDTH-1:0] wr_addr,
	input  wire [DWIDTH-1:0] wr_data,
	input  wire wr_ena,

	input  wire clk,
	input  wire rst
);

	// Signals
	reg [DWIDTH-1:0] ram [(1<<AWIDTH)-1:0];
	reg [DWIDTH-1:0] rd_data_r;
	reg rd_ena_r;

`ifdef SIM
	integer i;
	initial
		for (i=0; i<(1<<AWIDTH); i=i+1)
			ram[i] = 0;
`endif

	always @(posedge clk)
	begin
		// Read
		rd_data_r <= ram[rd_addr];

		// Write
		if (wr_ena)
			ram[wr_addr] <= wr_data;

		// Register the enable flag
		rd_ena_r <= rd_ena;

		// Final read register
		if (rd_ena_r)
			rd_data <= rd_data_r;
		else
			rd_data <= 0;
	end

endmodule // f15_line_mem
module delay_bit #(
	parameter integer DELAY = 1
)(
	input  wire d,
	output wire q,
	input  wire clk
);

	// Signals
	wire [4:0] addr = DELAY - 2;
	wire ff_in;

	// Generate SRL if needed (or bypass if not)
	generate
		if (DELAY > 17) begin
			SRLC32E srl_I (
				.Q(ff_in),
				.A(addr),
				.CE(1'b1),
				.CLK(clk),
				.D(d)
			);
		end else if (DELAY > 1) begin
			SRL16E srl_I (
				.Q(ff_in),
				.A0(addr[0]),
				.A1(addr[1]),
				.A2(addr[2]),
				.A3(addr[3]),
				.CE(1'b1),
				.CLK(clk),
				.D(d)
			);
		end else begin
			assign ff_in = d;
		end
	endgenerate

	// Generate flip-flop if needed (or bypass if not)
	generate
		if (DELAY > 0) begin
			FDRE ff_I (
				.Q(q),
				.C(clk),
				.CE(1'b1),
				.D(ff_in),
				.R(1'b0)
			);
		end else begin
			assign q = ff_in;
		end
	endgenerate

endmodule // delay_bit
module delay_bus #(
	parameter integer DELAY = 1,
	parameter integer WIDTH = 1
)(
	input  wire [WIDTH-1:0] d,
	output wire [WIDTH-1:0] q,
	input  wire clk
);
	genvar i;

	// Variables / Signals
	wire [4:0] addr = DELAY - 2;
	wire [WIDTH-1:0] ff_in;

	// Generate SRL if needed (or bypass if not)
	generate
		if (DELAY > 17) begin
			for (i=0; i<WIDTH; i=i+1)
				SRLC32E srl_I (
					.Q(ff_in[i]),
					.A(addr),
					.CE(1'b1),
					.CLK(clk),
					.D(d[i])
				);
		end else if (DELAY > 1) begin
			for (i=0; i<WIDTH; i=i+1)
				SRL16E srl_I (
					.Q(ff_in[i]),
					.A0(addr[0]),
					.A1(addr[1]),
					.A2(addr[2]),
					.A3(addr[3]),
					.CE(1'b1),
					.CLK(clk),
					.D(d[i])
				);
		end else begin
			assign ff_in = d;
		end
	endgenerate

	// Generate flip-flop if needed (or bypass if not)
	generate
		if (DELAY > 0) begin
			for (i=0; i<WIDTH; i=i+1)
				FDRE ff_I (
					.Q(q[i]),
					.C(clk),
					.CE(1'b1),
					.D(ff_in[i]),
					.R(1'b0)
				);
		end else begin
			assign q = ff_in;
		end
	endgenerate

endmodule // delay_bus
module f15_binmap #(
	parameter integer BIN_WIDTH = 6,
	parameter integer SCALE_FRAC_BITS = 8
)(
	input  wire [15:0] in_0,
	input  wire [15:0] offset_0,		// unsigned
	input  wire [15:0] scale_0,			// unsigned
	output reg  [BIN_WIDTH-1:0] bin_5,	// bin number
	output reg  sat_ind_5,				// saturation indicator
	input  wire clk,
	input  wire rst
);
	localparam integer TBI = 15 + SCALE_FRAC_BITS;	// Top-Bit-Index

	// Signals
	wire [47:0] dsp_pout_4;
	wire dsp_pat_match_4;


	// Main DSP
	// --------
	// computes (in - cfg_offset) * cfg_scale

	DSP48E1 #(
		.A_INPUT("DIRECT"),
		.B_INPUT("DIRECT"),
		.USE_DPORT("TRUE"),
		.USE_MULT("MULTIPLY"),
		.AUTORESET_PATDET("NO_RESET"),
		.MASK({1'b1, {(46-TBI){1'b0}}, {(TBI+1){1'b1}}}),
		.PATTERN(48'h000000000000),
		.SEL_MASK("MASK"),
		.SEL_PATTERN("PATTERN"),
		.USE_PATTERN_DETECT("PATDET"),
		.ACASCREG(1),
		.ADREG(1),
		.ALUMODEREG(1),
		.AREG(1),
		.BCASCREG(2),
		.BREG(2),
		.CARRYINREG(1),
		.CARRYINSELREG(1),
		.CREG(1),
		.DREG(1),
		.INMODEREG(1),
		.MREG(1),
		.OPMODEREG(1),
		.PREG(1),
		.USE_SIMD("ONE48")
	)
	dsp_binmap_I (
		.PATTERNDETECT(dsp_pat_match_4),
		.P(dsp_pout_4),
		.ACIN(30'h0),
		.BCIN(18'h0),
		.CARRYCASCIN(1'h0),
		.MULTSIGNIN(1'h0),
		.PCIN(48'h000000000000),
		.ALUMODE(4'b0000),		// Z + X + Y + CIN
		.CARRYINSEL(3'h0),
		.CEINMODE(1'b1),
		.CLK(clk),
		.INMODE(5'b01100),		// B=B2, A=D-A2
		.OPMODE(7'b0000101),	// X=M1, Y=M2, Z=0
		.RSTINMODE(rst),
		.A({14'h0, offset_0}),
		.B({ 2'h0, scale_0}),
		.C({48'h0}),
		.CARRYIN(1'b0),
		.D({ 9'h0, in_0}),
		.CEA1(1'b0),
		.CEA2(1'b1),
		.CEAD(1'b1),
		.CEALUMODE(1'b1),
		.CEB1(1'b1),
		.CEB2(1'b1),
		.CEC(1'b1),
		.CECARRYIN(1'b1),
		.CECTRL(1'b1),
		.CED(1'b1),
		.CEM(1'b1),
		.CEP(1'b1),
		.RSTA(rst),
		.RSTALLCARRYIN(rst),
		.RSTALUMODE(rst),
		.RSTB(rst),
		.RSTC(rst),
		.RSTCTRL(rst),
		.RSTD(rst),
		.RSTM(rst),
		.RSTP(rst)
	);


	// Post-DSP mapping & saturation
	// -----------------------------

	always @(posedge clk)
	begin
		if (rst == 1) begin
			bin_5 <= 0;
			sat_ind_5 <= 0;
		end else begin
			// Undeflow
			if (dsp_pout_4[47] == 1) begin
				bin_5 <= {BIN_WIDTH{1'b0}};
				sat_ind_5 <= 1;

			// Overflow
			end else if (dsp_pat_match_4 == 0) begin
				bin_5 <= {BIN_WIDTH{1'b1}};
				sat_ind_5 <= 1;

			// In-range
			end else begin
				bin_5 <= dsp_pout_4[TBI:TBI-BIN_WIDTH+1];
				sat_ind_5 <= 0;
			end
		end
	end

endmodule // f15_binmap
module f15_eoseq #(
	parameter integer WIDTH = 16
)(
	input  wire [WIDTH-1:0] in_data,
	input  wire in_valid,
	input  wire in_last,
	output reg  [WIDTH-1:0] out_data,
	output reg  out_valid,
	output reg  out_last,
	input  wire clk,
	input  wire rst
);

	// Signals
	reg [WIDTH-1:0] buf_data;
	reg buf_valid;
	reg buf_last;

	wire flip;
	reg odd;
	reg sel;

	// Control
	always @(posedge clk)
		if (rst)
			odd <= 1'b0;
		else
			odd <= ~(in_last & in_valid) & (odd ^ in_valid);

	always @(posedge clk)
		if (rst)
			sel <= 1'b0;
		else if (flip)
			sel <= ~sel;

	assign flip = ~in_valid | (in_last & ~odd);

	// Buffer
	always @(posedge clk)
	begin
		buf_data  <= in_data;
		buf_valid <= in_valid;
		buf_last  <= in_last;
	end

	// Output
	always @(posedge clk)
	begin
		if (sel) begin
			out_data  <= buf_data;
			out_valid <= buf_valid;
			out_last  <= buf_last;
		end else begin
			out_data  <= in_data;
			out_valid <= in_valid;
			out_last  <= in_last;
		end
	end

endmodule // f15_eoseq
module f15_packetizer #(
	parameter integer BIN_WIDTH = 6,
	parameter integer DECIM_WIDTH = 10
)(
	input  wire [BIN_WIDTH-1:0] in_bin_addr,
	input  wire in_bin_last,
	input  wire [7:0] in_histo,
	input  wire [7:0] in_spectra_max,
	input  wire [7:0] in_spectra_avg,
	input  wire in_last,
	input  wire in_valid,

	output reg [31:0] out_data,
	output reg out_last,
	output reg out_eob,
	output reg out_valid,

	input  wire [DECIM_WIDTH-1:0] cfg_decim,
	input  wire cfg_decim_changed,

	input  wire clk,
	input  wire rst
);

	// FSM
	localparam
		ST_WAIT = 0,
		ST_SEND_HISTO = 1,
		ST_SEND_MAX = 2,
		ST_SEND_AVG = 3;

	reg [1:0] state;

	// Signals
	reg [DECIM_WIDTH:0] decim_cnt;
	reg [1:0] bcnt;

	// 1-in-N decimation counter
	always @(posedge clk)
	begin
		if (rst)
			decim_cnt <= 0;
		else if (cfg_decim_changed)
			// Force Reload
			decim_cnt <= { 1'b0, cfg_decim };
		else if (in_valid & in_bin_last & in_last)
			if (decim_cnt[DECIM_WIDTH])
				// Reload
				decim_cnt <= { 1'b0, cfg_decim };
			else
				// Just decrement
				decim_cnt <= decim_cnt - 1;
	end

	// FSM
	always @(posedge clk)
	begin
		if (rst)
			state <= ST_WAIT;
		else if (in_valid & in_last)
			case (state)
				ST_WAIT:
					if (in_bin_last & decim_cnt[DECIM_WIDTH])
						state <= ST_SEND_HISTO;

				ST_SEND_HISTO:
					if (in_bin_last)
						state <= ST_SEND_MAX;

				ST_SEND_MAX:
					state <= ST_SEND_AVG;

				ST_SEND_AVG:
					state <= ST_WAIT;
			endcase
	end

	// Byte counter
	always @(posedge clk)
	begin
		if (rst)
			bcnt <= 2'b00;
		else if (in_valid)
			if (in_last | (bcnt == 2'b11))
				bcnt <= 2'b00;
			else
				bcnt <= bcnt + 1;
	end

	// Input mux & shift register
	always @(posedge clk)
	begin
		if (in_valid)
		begin
			// Shift
			out_data[31:8] <= out_data[23:0];

			// New LSBs
			case (state)
				ST_SEND_HISTO: out_data[7:0] <= in_histo;
				ST_SEND_MAX:   out_data[7:0] <= in_spectra_max;
				ST_SEND_AVG:   out_data[7:0] <= in_spectra_avg;
			endcase
		end
	end

	// Output last, eob, valid
	always @(posedge clk)
	begin
		if (rst) begin
			out_last  <= 1'b0;
			out_eob   <= 1'b0;
			out_valid <= 1'b0;
		end else begin
			out_last  <= in_last;
			out_eob   <= (state == ST_SEND_AVG);
			out_valid <= in_valid & (in_last | bcnt == 2'b11) & (state != ST_WAIT);
		end
	end

endmodule // f15_packetizer
module f15_histo_mem #(
	parameter integer ADDR_WIDTH = 16
)(
	// Port A Read
	input  wire [ADDR_WIDTH-1:0] addr_AR,
	output reg  [8:0] data_AR,
	input  wire ena_AR,

	// Port A Write
	input  wire [ADDR_WIDTH-1:0] addr_AW,
	input  wire [8:0] data_AW,
	input  wire ena_AW,

	// Port B Read
	input  wire [ADDR_WIDTH-1:0] addr_BR,
	output reg  [8:0] data_BR,
	input  wire ena_BR,

	// Port B Write
	input  wire [ADDR_WIDTH-1:0] addr_BW,
	input  wire [8:0] data_BW,
	input  wire ena_BW,

	// Error detection
	output reg  conflict_A,
	output reg  conflict_B,

	// Common
	input  wire clk,
	input  wire rst
);

	// Signals
		// Memory banks IF
	wire [ADDR_WIDTH-2:0] even_addra, odd_addra;
	wire [ADDR_WIDTH-2:0] even_addrb, odd_addrb;
	wire [8:0] even_dia, odd_dia;
	wire [8:0] even_dib, odd_dib;
	wire [8:0] even_doa, odd_doa;
	wire [8:0] even_dob, odd_dob;
	wire even_wea, odd_wea;
	wire even_web, odd_web;
	wire even_rea, odd_rea;
	wire even_reb, odd_reb;

		// Control
	wire sel_A, sel_B;


	// Mux selection
	assign sel_A = ena_AR ? addr_AR[0] : ~addr_AW[0];
	assign sel_B = ena_BR ? addr_BR[0] : ~addr_BW[0];

	// Conflict detection
	always @(posedge clk)
	begin
		conflict_A <= !(addr_AR[0] ^ addr_AW[0]) & ena_AR & ena_AW;
		conflict_B <= !(addr_BR[0] ^ addr_BW[0]) & ena_BR & ena_BW;
	end

	// Control signals
	assign even_wea =  sel_A & ena_AW;
	assign odd_wea  = !sel_A & ena_AW;
	assign even_web =  sel_B & ena_BW;
	assign odd_web  = !sel_B & ena_BW;
	assign even_rea = !sel_A & ena_AR;
	assign odd_rea  =  sel_A & ena_AR;
	assign even_reb = !sel_B & ena_BR;
	assign odd_reb  =  sel_B & ena_BR;

	// Address path mapping
	assign even_addra = sel_A ? addr_AW[ADDR_WIDTH-1:1] : addr_AR[ADDR_WIDTH-1:1];
	assign even_addrb = sel_B ? addr_BW[ADDR_WIDTH-1:1] : addr_BR[ADDR_WIDTH-1:1];
	assign odd_addra  = sel_A ? addr_AR[ADDR_WIDTH-1:1] : addr_AW[ADDR_WIDTH-1:1];
	assign odd_addrb  = sel_B ? addr_BR[ADDR_WIDTH-1:1] : addr_BW[ADDR_WIDTH-1:1];

	// Data path mapping
	assign even_dia = data_AW;
	assign odd_dia  = data_AW;
	assign even_dib = data_BW;
	assign odd_dib  = data_BW;

	always @(posedge clk)
	begin
		data_AR <= even_doa | odd_doa;
		data_BR <= even_dob | odd_dob;
	end

	// Instanciate memory banks
	f15_histo_mem_bank #(
		.ADDR_WIDTH(ADDR_WIDTH-1)
	) mem_even (
		.addra(even_addra),
		.addrb(even_addrb),
		.dia(even_dia),
		.dib(even_dib),
		.doa(even_doa),
		.dob(even_dob),
		.wea(even_wea),
		.web(even_web),
		.rea(even_rea),
		.reb(even_reb),
		.clk(clk),
		.rst(rst)
	);

	f15_histo_mem_bank #(
		.ADDR_WIDTH(ADDR_WIDTH-1)
	) mem_odd (
		.addra(odd_addra),
		.addrb(odd_addrb),
		.dia(odd_dia),
		.dib(odd_dib),
		.doa(odd_doa),
		.dob(odd_dob),
		.wea(odd_wea),
		.web(odd_web),
		.rea(odd_rea),
		.reb(odd_reb),
		.clk(clk),
		.rst(rst)
	);

endmodule // f15_histo_mem
module rng(
	output reg  [31:0] out,
	input  wire clk,
	input  wire rst
);

	// Signals
	wire [4:0] out5, out5rev;
	wire [7:0] out8;
	wire [11:0] out12;
	wire [15:0] out16;

	// Instanciate 4 LFSRs of different lengths
	lfsr #(.WIDTH( 5), .POLY( 5'b01001)) lfsr5  (.out(out5),  .clk(clk), .rst(rst));
	lfsr #(.WIDTH( 8), .POLY( 8'h71   )) lfsr8  (.out(out8),  .clk(clk), .rst(rst));
	lfsr #(.WIDTH(12), .POLY(12'hc11  )) lfsr12 (.out(out12), .clk(clk), .rst(rst));
	lfsr #(.WIDTH(16), .POLY(16'h6701 )) lfsr16 (.out(out16), .clk(clk), .rst(rst));

	// Reverse the 5 bit LFSR output
	genvar i;
	generate
		for (i=0; i<5; i=i+1)
			assign out5rev[i] = out5[4-i];
	endgenerate

	// Combine the outputs 'somehow'
	always @(posedge clk)
		out <= {
			out16[15:11] ^ out5rev,		// 5 bits
			out16[10:2],				// 9 bits
			out16[1:0] ^ out12[11:10],	// 2 bits
			out12[9:2],					// 8 bits
			out12[1:0] ^ out8[7:6],		// 2 bits
			out8[5:0]					// 6 bits
		};

endmodule // rng
module lfsr #(
	parameter integer WIDTH = 8,
	parameter POLY = 8'h71
)(
	output reg  [WIDTH-1:0] out,
	input  wire clk,
	input  wire rst
);

	// Signals
	wire fb;

	// Linear Feedback
	assign fb = ^(out & POLY);

	// Register
	always @(posedge clk)
		if (rst)
			out <= { {(WIDTH-1){1'b0}}, 1'b1 };
		else
			out <= { fb, out[WIDTH-1:1] };

endmodule // lfsr
module axi_logpwr #(
	parameter [1:0] RANDOM_MODE = 2'b11
)(
	input  clk, input reset,
	input  [31:0] i_tdata, input  i_tlast, input  i_tvalid, output i_tready,
	output [15:0] o_tdata, output o_tlast, output o_tvalid, input  o_tready
);

	// Signals
	reg ready;
	reg valid_1;
	wire valid_12;
	wire last_12;

	wire [31:0] rng;

	wire [15:0] in_real_0;
	wire [15:0] in_imag_0;
	wire [15:0] out_logpwr_12;

	wire [16:0] fifo_di;
	wire [16:0] fifo_do;
	wire fifo_wren;
	wire fifo_afull;
	wire fifo_rden;
	wire fifo_empty;

 	// Input control
	assign in_real_0 = i_tdata[31:16];
	assign in_imag_0 = i_tdata[15:0];

	always @(posedge clk)
	begin
		ready <= ~fifo_afull | o_tready;
		valid_1 <= i_tvalid & ready;
	end

	assign i_tready = ready;

	// Delays
	delay_bit #(11) dl_valid (valid_1, valid_12, clk);
	delay_bit #(12) dl_last  (i_tlast, last_12, clk);

	// RNG Instance
    rng rng_I (
		.out(rng),
		.clk(clk),
		.rst(reset)
	);

	// logpwr Instance
	f15_logpwr logpwr_I (
		.in_real_0(in_real_0),
		.in_imag_0(in_imag_0),
		.out_12(out_logpwr_12),
		.rng(rng),
		.random_mode(RANDOM_MODE),
		.clk(clk),
		.rst(reset)
	);

	// Output FIFO
	assign fifo_di   = { last_12, out_logpwr_12 };
	assign fifo_wren = { valid_12 };

	fifo_srl #(
		.WIDTH(17),
		.LOG2_DEPTH(6),
		.AFULL_LEVEL(49)
	) fifo_I (
		.di(fifo_di),
		.wren(fifo_wren),
		.afull(fifo_afull),
		.do(fifo_do),
		.rden(fifo_rden),
		.empty(fifo_empty),
		.clk(clk),
		.rst(reset)
	);

	assign o_tdata  = fifo_do[15:0];
	assign o_tlast  = fifo_do[16];
	assign o_tvalid = ~fifo_empty;

	assign fifo_rden = ~fifo_empty & o_tready;

endmodule // axi_logpwr
module f15_maxhold #(
	parameter integer Y_WIDTH = 12,
	parameter integer X_WIDTH = 16,
	parameter integer FRAC_WIDTH = 8
)(
	input  wire [Y_WIDTH-1:0] yin_0,
	input  wire [X_WIDTH-1:0] x_0,
	input  wire [15:0] rng_0,
	input  wire [15:0] epsilon_0,
	input  wire clear_0,
	output wire [Y_WIDTH-1:0] yout_4,
	input  wire clk,
	input  wire rst
);

	 localparam integer I_WIDTH = X_WIDTH + FRAC_WIDTH;

	// Signals
	reg [X_WIDTH-1:0] x_1;
	reg [I_WIDTH  :0] y_1;
	reg [Y_WIDTH  :0] d_1;
	reg clear_1;

	reg [Y_WIDTH-1:0] y_2;

	// Stage 1
	always @(posedge clk)
	begin
		x_1 <= x_0;
		y_1 <= { 1'b0, yin_0, rng_0[I_WIDTH-Y_WIDTH-1:0] } - epsilon_0;
		d_1 <= { 1'b0, yin_0 } - { 1'b0, x_0[X_WIDTH-1:X_WIDTH-Y_WIDTH] };
		clear_1 <= clear_0;
	end

	// Stage 2
	always @(posedge clk)
	begin
		if (clear_1)
			y_2 <= 0;
		else if (d_1[Y_WIDTH])
			// x is larger, use this
			y_2 <= x_1[X_WIDTH-1:X_WIDTH-Y_WIDTH];
		else
			// y is larger, take old y with small decay
			if (y_1[I_WIDTH])
				y_2 <= 0;
			else
				y_2 <= y_1[I_WIDTH-1:I_WIDTH-Y_WIDTH];
	end

	// Apply two more delay to match the avg block
	delay_bus #(2, Y_WIDTH) dl_y (y_2, yout_4, clk);

endmodule // f15_maxhold
module pass_thru_and_invert (
  input clk, input reset,
  input [31:0] i_tdata, input [127:0] i_tuser, input i_tlast, input i_tvalid, output i_tready,
  output [31:0] pass_thru_tdata, output [127:0] pass_thru_tuser, output pass_thru_tlast, output pass_thru_tvalid, input pass_thru_tready,
  output [31:0] invert_tdata, output [127:0] invert_tuser, output invert_tlast, output invert_tvalid, input invert_tready);

  wire [31:0] out_tdata[0:1];
  wire [127:0] out_tuser[0:1];
  wire [1:0] out_tlast;
  wire [1:0] out_tvalid;
  wire [1:0] out_tready;
  split_stream_fifo #(
    .WIDTH(32+128), .ACTIVE_MASK(4'b0011))
  split_stream_fifo (
    .clk(clk), .reset(reset), .clear(1'b0),
    .i_tdata({i_tuser, i_tdata}), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
    .o0_tdata({out_tuser[0], out_tdata[0]}), .o0_tlast(out_tlast[0]), .o0_tvalid(out_tvalid[0]), .o0_tready(out_tready[0]),
    .o1_tdata({out_tuser[1], out_tdata[1]}), .o1_tlast(out_tlast[1]), .o1_tvalid(out_tvalid[1]), .o1_tready(out_tready[1]),
    .o2_tready(1'b1), .o3_tready(1'b1));

  // Caculate inverted data + a register stage to show a path with a different length
  axi_fifo_flop #(.WIDTH(32+128+1))
  axi_fifo_flop (
    .clk(clk), .reset(reset), .clear(),
    .i_tdata({out_tuser[1],out_tlast[1],~out_tdata[1]}), .i_tvalid(out_tvalid[1]), .i_tready(out_tready[1]),
    .o_tdata({invert_tuser,invert_tlast,invert_tdata}), .o_tvalid(invert_tvalid), .o_tready(invert_tready));

  // Pass through data
  assign pass_thru_tdata = out_tdata[0];
  assign pass_thru_tuser = out_tuser[0];
  assign pass_thru_tlast = out_tlast[0];
  assign pass_thru_tvalid = out_tvalid[0];
  assign out_tready[0] = pass_thru_tready;

endmodule
module cam #(
    // search data bus width
    parameter DATA_WIDTH = 64,
    // memory size in log2(words)
    parameter ADDR_WIDTH = 5,
    // CAM style (SRL, BRAM)
    parameter CAM_STYLE = "SRL",
    // width of data bus slices
    parameter SLICE_WIDTH = 4
)
(
    input  wire                     clk,
    input  wire                     rst,

    input  wire [ADDR_WIDTH-1:0]    write_addr,
    input  wire [DATA_WIDTH-1:0]    write_data,
    input  wire                     write_delete,
    input  wire                     write_enable,
    output wire                     write_busy,

    input  wire [DATA_WIDTH-1:0]    compare_data,
    output wire [2**ADDR_WIDTH-1:0] match_many,
    output wire [2**ADDR_WIDTH-1:0] match_single,
    output wire [ADDR_WIDTH-1:0]    match_addr,
    output wire                     match
);

generate
    if (CAM_STYLE == "SRL") begin
        cam_srl #(
            .DATA_WIDTH(DATA_WIDTH),
            .ADDR_WIDTH(ADDR_WIDTH),
            .SLICE_WIDTH(SLICE_WIDTH)
        )
        cam_inst (
            .clk(clk),
            .rst(rst),
            .write_addr(write_addr),
            .write_data(write_data),
            .write_delete(write_delete),
            .write_enable(write_enable),
            .write_busy(write_busy),
            .compare_data(compare_data),
            .match_many(match_many),
            .match_single(match_single),
            .match_addr(match_addr),
            .match(match)
        );
    end else if (CAM_STYLE == "BRAM") begin
        cam_bram #(
            .DATA_WIDTH(DATA_WIDTH),
            .ADDR_WIDTH(ADDR_WIDTH),
            .SLICE_WIDTH(SLICE_WIDTH)
        )
        cam_inst (
            .clk(clk),
            .rst(rst),
            .write_addr(write_addr),
            .write_data(write_data),
            .write_delete(write_delete),
            .write_enable(write_enable),
            .write_busy(write_busy),
            .compare_data(compare_data),
            .match_many(match_many),
            .match_single(match_single),
            .match_addr(match_addr),
            .match(match)
        );
    end
endgenerate

endmodule
module cam_priority_encoder #
(
    parameter WIDTH = 4,
    // LSB priority: "LOW", "HIGH"
    parameter LSB_PRIORITY = "LOW"
)
(
    input  wire [WIDTH-1:0]         input_unencoded,
    output wire                     output_valid,
    output wire [$clog2(WIDTH)-1:0] output_encoded,
    output wire [WIDTH-1:0]         output_unencoded
);

// power-of-two width
parameter W1 = 2**$clog2(WIDTH);
parameter W2 = W1/2;

generate
    if (WIDTH == 2) begin
        // two inputs - just an OR gate
        assign output_valid = |input_unencoded;
        if (LSB_PRIORITY == "LOW") begin
            assign output_encoded = input_unencoded[1];
        end else begin
            assign output_encoded = ~input_unencoded[0];
        end
    end else begin
        // more than two inputs - split into two parts and recurse
        // also pad input to correct power-of-two width
        wire [$clog2(W2)-1:0] out1, out2;
        wire valid1, valid2;
        cam_priority_encoder #(
            .WIDTH(W2),
            .LSB_PRIORITY(LSB_PRIORITY)
        )
        priority_encoder_inst1 (
            .input_unencoded(input_unencoded[W2-1:0]),
            .output_valid(valid1),
            .output_encoded(out1)
        );
        cam_priority_encoder #(
            .WIDTH(W2),
            .LSB_PRIORITY(LSB_PRIORITY)
        )
        priority_encoder_inst2 (
            .input_unencoded({{W1-WIDTH{1'b0}}, input_unencoded[WIDTH-1:W2]}),
            .output_valid(valid2),
            .output_encoded(out2)
        );
        // multiplexer to select part
        assign output_valid = valid1 | valid2;
        if (LSB_PRIORITY == "LOW") begin
            assign output_encoded = valid2 ? {1'b1, out2} : {1'b0, out1};
        end else begin
            assign output_encoded = valid1 ? {1'b0, out1} : {1'b1, out2};
        end
    end
endgenerate

// unencoded output
assign output_unencoded = 1 << output_encoded;

endmodule
module sync_bits
(
  input [NUM_OF_BITS-1:0] in,
  input out_resetn,
  input out_clk,
  output [NUM_OF_BITS-1:0] out
);

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

reg [NUM_OF_BITS-1:0] cdc_sync_stage1 = 'h0;
reg [NUM_OF_BITS-1:0] cdc_sync_stage2 = 'h0;

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

assign out = ASYNC_CLK ? cdc_sync_stage2 : in;

endmodule
module dmac_dest_fifo_inf (
  input clk,
  input resetn,

  input enable,
  output enabled,
  input sync_id,
  output sync_id_ret,

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

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

        output xfer_req,

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

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

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

parameter ID_WIDTH = 3;
parameter DATA_WIDTH = 64;
parameter BEATS_PER_BURST_WIDTH = 4;

assign sync_id_ret = sync_id;
wire data_enabled;

wire _fifo_ready;
assign fifo_ready = _fifo_ready | ~enabled;

reg en_d1;
wire data_ready;
wire data_valid;

always @(posedge clk)
begin
  if (resetn == 1'b0) begin
    en_d1 <= 1'b0;
  end else begin
    en_d1 <= en;
  end
end

assign underflow = en_d1 & (~data_valid | ~enable);
assign data_ready = en_d1 & (data_valid | ~enable);
assign valid = en_d1 & data_valid & enable;

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

  .enable(enable),
  .enabled(data_enabled),
  .sync_id(sync_id),
        .xfer_req(xfer_req),

  .request_id(request_id),
  .response_id(data_id),
  .eot(data_eot),
  
  .req_valid(req_valid),
  .req_ready(req_ready),
  .req_last_burst_length(req_last_burst_length),

  .s_axi_ready(_fifo_ready),
  .s_axi_valid(fifo_valid),
  .s_axi_data(fifo_data),
  .m_axi_ready(data_ready),
  .m_axi_valid(data_valid),
  .m_axi_data(dout),
  .m_axi_last()
);

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

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

  .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_dest_axi_stream (
  input s_axis_aclk,
  input s_axis_aresetn,

  input enable,
  output enabled,
  input sync_id,
  output sync_id_ret,
        output xfer_req,

  input [ID_WIDTH-1:0] request_id,
  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 req_valid,
  output req_ready,
  input [BEATS_PER_BURST_WIDTH-1:0] req_last_burst_length,
        input req_xlast,

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

parameter ID_WIDTH = 3;
parameter S_AXIS_DATA_WIDTH = 64;
parameter BEATS_PER_BURST_WIDTH = 4;

reg req_xlast_d = 1'b0;

assign sync_id_ret = sync_id;
wire data_enabled;
wire _fifo_ready;
wire m_axis_last_s;

// We are not allowed to just de-assert valid, but if the streaming target does
// not accept any samples anymore we'd lock up the DMA core. So retain the last
// beat when disabled until it is accepted. But if in the meantime the DMA core
// is re-enabled and new data becomes available overwrite the old.

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

assign m_axis_last = (req_xlast_d == 1'b1) ? m_axis_last_s : 1'b0;

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

  .enable(enable),
  .enabled(data_enabled),
  .sync_id(sync_id),
        .xfer_req(xfer_req),

  .request_id(request_id),
  .response_id(data_id),
  .eot(data_eot),

  .req_valid(req_valid),
  .req_ready(req_ready),
  .req_last_burst_length(req_last_burst_length),

  .m_axi_ready(m_axis_ready),
  .m_axi_valid(m_axis_valid),
  .m_axi_data(m_axis_data),
        .m_axi_last(m_axis_last_s),
  .s_axi_ready(_fifo_ready),
  .s_axi_valid(fifo_valid),
  .s_axi_data(fifo_data)
);

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

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

  .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)
);

assign fifo_ready = _fifo_ready | ~enabled;

endmodule
module dmac_src_axi_stream (
  input s_axis_aclk,
  input s_axis_aresetn,

  input enable,
  output enabled,
  input sync_id,
  output sync_id_ret,

  input [ID_WIDTH-1:0] request_id,
  output [ID_WIDTH-1:0] response_id,
  input 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,
  output s_axis_xfer_req,

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

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

parameter ID_WIDTH = 3;
parameter S_AXIS_DATA_WIDTH = 64;
parameter LENGTH_WIDTH = 24;
parameter BEATS_PER_BURST_WIDTH = 4;

reg needs_sync = 1'b0;
wire sync = s_axis_user[0];
wire has_sync = ~needs_sync | sync;
wire sync_valid = s_axis_valid & has_sync;
assign sync_id_ret = sync_id;

always @(posedge s_axis_aclk)
begin
  if (s_axis_aresetn == 1'b0) begin
    needs_sync <= 1'b0;
  end else begin
    if (s_axis_valid && s_axis_ready && sync) begin
      needs_sync <= 1'b0;
    end else if (req_valid && req_ready) begin
      needs_sync <= req_sync_transfer_start;
    end
  end
end

dmac_data_mover # (
  .ID_WIDTH(ID_WIDTH),
  .DATA_WIDTH(S_AXIS_DATA_WIDTH),
  .DISABLE_WAIT_FOR_ID(0),
  .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH)
) i_data_mover (
  .clk(s_axis_aclk),
  .resetn(s_axis_aresetn),

  .enable(enable),
  .enabled(enabled),
  .sync_id(sync_id),

  .xfer_req(s_axis_xfer_req),

  .request_id(request_id),
  .response_id(response_id),
  .eot(eot),
  
  .req_valid(req_valid),
  .req_ready(req_ready),
  .req_last_burst_length(req_last_burst_length),

  .s_axi_ready(s_axis_ready),
  .s_axi_valid(sync_valid),
  .s_axi_data(s_axis_data),
  .m_axi_ready(fifo_ready),
  .m_axi_valid(fifo_valid),
  .m_axi_data(fifo_data)
);

endmodule
module dmac_2d_transfer (
  input req_aclk,
  input req_aresetn,

  input req_valid,
  output reg req_ready,

  input [31:BYTES_PER_BEAT_WIDTH_DEST] req_dest_address,
  input [31:BYTES_PER_BEAT_WIDTH_SRC] req_src_address,
  input [DMA_LENGTH_WIDTH-1:0] req_x_length,
  input [DMA_LENGTH_WIDTH-1:0] req_y_length,
  input [DMA_LENGTH_WIDTH-1:0] req_dest_stride,
  input [DMA_LENGTH_WIDTH-1:0] req_src_stride,
  input req_sync_transfer_start,
  output reg req_eot,
  
  output reg out_req_valid,
  input out_req_ready,
  output [31:BYTES_PER_BEAT_WIDTH_DEST] out_req_dest_address,
  output [31:BYTES_PER_BEAT_WIDTH_SRC] out_req_src_address,
  output [DMA_LENGTH_WIDTH-1:0] out_req_length,
  output reg out_req_sync_transfer_start,
  input out_eot
);

parameter DMA_LENGTH_WIDTH = 24;
parameter BYTES_PER_BEAT_WIDTH_SRC = 3;
parameter BYTES_PER_BEAT_WIDTH_DEST = 3;

reg [31:BYTES_PER_BEAT_WIDTH_DEST] dest_address;
reg [31:BYTES_PER_BEAT_WIDTH_SRC] src_address;
reg [DMA_LENGTH_WIDTH-1:0] x_length;
reg [DMA_LENGTH_WIDTH-1:0] y_length;
reg [DMA_LENGTH_WIDTH-1:0] dest_stride;
reg [DMA_LENGTH_WIDTH-1:0] src_stride;

reg [1:0] req_id;
reg [1:0] eot_id;
reg [3:0] last_req;

assign out_req_dest_address = dest_address;
assign out_req_src_address = src_address;
assign out_req_length = x_length;

always @(posedge req_aclk)
begin
  if (req_aresetn == 1'b0) begin
    req_id <= 2'b0;
    eot_id <= 2'b0;
    req_eot <= 1'b0;
  end else begin
    if (out_req_valid && out_req_ready) begin
      req_id <= req_id + 1'b1;
      last_req[req_id] <= y_length == 0;
    end
    req_eot <= 1'b0;
    if (out_eot) begin
      eot_id <= eot_id + 1'b1;
      req_eot <= last_req[eot_id];
    end
  end
end

always @(posedge req_aclk)
begin
  if (req_aresetn == 1'b0) begin
    dest_address <= 'h00;
    src_address <= 'h00;
    x_length <= 'h00;
    y_length <= 'h00;
    dest_stride <= 'h00;
    src_stride <= 'h00;
    req_ready <= 1'b1;
    out_req_valid <= 1'b0;
    out_req_sync_transfer_start <= 1'b0;
  end else begin
    if (req_ready) begin
      if (req_valid) begin
        dest_address <= req_dest_address;
        src_address <= req_src_address;
        x_length <= req_x_length;
        y_length <= req_y_length;
        dest_stride <= req_dest_stride;
        src_stride <= req_src_stride;
        out_req_sync_transfer_start <= req_sync_transfer_start;
        req_ready <= 1'b0;
        out_req_valid <= 1'b1;
      end
    end else begin
      if (out_req_valid && out_req_ready) begin
        dest_address <= dest_address + dest_stride[DMA_LENGTH_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST];
        src_address <= src_address + src_stride[DMA_LENGTH_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC];
        y_length <= y_length - 1'b1;
        out_req_sync_transfer_start <= 1'b0;
        if (y_length == 0) begin
          out_req_valid <= 1'b0;
          req_ready <= 1'b1;
        end
      end
    end
  end
end

endmodule
module dmac_src_fifo_inf (
  input clk,
  input resetn,

  input enable,
  output enabled,
  input sync_id,
  output sync_id_ret,

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

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

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

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

parameter ID_WIDTH = 3;
parameter DATA_WIDTH = 64;
parameter BEATS_PER_BURST_WIDTH = 4;

wire ready;

reg needs_sync = 1'b0;
wire has_sync = ~needs_sync | sync;
wire sync_valid = en & ready & has_sync;

always @(posedge clk)
begin
  if (resetn == 1'b0) begin
    needs_sync <= 1'b0;
  end else begin
    if (ready && en && sync) begin
      needs_sync <= 1'b0;
    end else if (req_valid && req_ready) begin
      needs_sync <= req_sync_transfer_start;
    end
  end
end

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

assign sync_id_ret = sync_id;

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

  .enable(enable),
  .enabled(enabled),
  .sync_id(sync_id),

  .xfer_req(xfer_req),

  .request_id(request_id),
  .response_id(response_id),
  .eot(eot),
  
  .req_valid(req_valid),
  .req_ready(req_ready),
  .req_last_burst_length(req_last_burst_length),

  .s_axi_ready(ready),
  .s_axi_valid(sync_valid),
  .s_axi_data(din),
  .m_axi_ready(fifo_ready),
  .m_axi_valid(fifo_valid),
  .m_axi_data(fifo_data),
  .m_axi_last()
);

endmodule
module splitter (
  input clk,
  input resetn,

  input s_valid,
  output s_ready,

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

parameter NUM_M = 2;

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

parameter DATA_WIDTH = 32;

parameter FORWARD_REGISTERED = 0;
parameter BACKWARD_REGISTERED = 0;

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