dakies/OSS_Verilog huggingface dataset:
module zq_calib_ctrl #(parameter TCQ = 100, MAINT_PRESCALER_PERIOD = 200000) (
	input clk,
	input rst,
	
	input zq_ack,
	output reg zq_request,
	
	input dfi_init_complete,
	input maint_prescaler_tick
);

	function integer clogb2 (input integer size); // ceiling logb2
    begin
      size = size - 1;
      for (clogb2=1; size>1; clogb2=clogb2+1)
            size = size >> 1;
    end
	endfunction // clogb2

	// ZQ timebase.  Nominally 128 mS
	localparam MAINT_PRESCALER_PERIOD_NS = MAINT_PRESCALER_PERIOD / 1000;
	localparam tZQI = 128_000_000;
	localparam ZQ_TIMER_DIV = tZQI/MAINT_PRESCALER_PERIOD_NS;
	localparam ZQ_TIMER_WIDTH = clogb2(ZQ_TIMER_DIV + 1);
	localparam ONE = 1;
	
	generate
		begin : zq_cntrl
			reg zq_tick = 1'b0;
			
			if (ZQ_TIMER_DIV !=0) begin : zq_timer
				reg [ZQ_TIMER_WIDTH-1:0] zq_timer_r;
				reg [ZQ_TIMER_WIDTH-1:0] zq_timer_ns;
				
				always @(/*AS*/dfi_init_complete or maint_prescaler_tick
				or zq_tick or zq_timer_r) begin
					zq_timer_ns = zq_timer_r;
					if (~dfi_init_complete || zq_tick)
						zq_timer_ns = ZQ_TIMER_DIV[ZQ_TIMER_WIDTH-1:0];
					else if (|zq_timer_r && maint_prescaler_tick)
						zq_timer_ns = zq_timer_r - ONE[ZQ_TIMER_WIDTH-1:0];
				end
				
				always @(posedge clk) zq_timer_r <= #TCQ zq_timer_ns;
				
				always @(/*AS*/maint_prescaler_tick or zq_timer_r)
					zq_tick = (zq_timer_r == ONE[ZQ_TIMER_WIDTH-1:0] && maint_prescaler_tick);
			end // zq_timer

			// ZQ request. Set request with timer tick, and when exiting PHY init.  Never
			// request if ZQ_TIMER_DIV == 0.
			begin : zq_request_logic
				wire zq_clears_zq_request = zq_ack;
				reg zq_request_r;
				wire zq_request_ns = ~rst && ((~dfi_init_complete && (ZQ_TIMER_DIV != 0)) || 
					(zq_request_r && ~zq_clears_zq_request) || zq_tick);
				
				always @(posedge clk) zq_request_r <= #TCQ zq_request_ns;
				
				always @(/*AS*/dfi_init_complete or zq_request_r)
					zq_request = dfi_init_complete && zq_request_r;
			end // zq_request_logic
		end
	endgenerate

endmodule
module autoref_ctrl #(parameter TCQ = 100) (
	input clk,
	input rst,
	
	input autoref_en,
	input[27:0] autoref_interval,
	input autoref_ack,
	output autoref_req,
	
	input dfi_init_complete,
	input maint_prescaler_tick
);

	localparam ONE = 1;
	 
	reg [27:0] autoref_timer_r, autoref_timer;
	reg autoref_request_r;
	reg ref_en_r;
	 
	always @* begin
		autoref_timer = autoref_timer_r;
		
		if(~dfi_init_complete || autoref_ack || (~ref_en_r && autoref_en)) begin
			autoref_timer = autoref_interval;
		end
		else if (|autoref_timer_r && maint_prescaler_tick) begin
			autoref_timer = autoref_timer_r - ONE[0+:28];
		end
	end //always
	 
	wire autoref_timer_one = maint_prescaler_tick && (autoref_timer_r == ONE[0+:28]);
	 
	wire autoref_request = ~rst && dfi_init_complete && autoref_en && (
								(~autoref_ack && (autoref_request_r || autoref_timer_one)));
	 
	always @(posedge clk) begin
		autoref_timer_r <= #TCQ autoref_timer;
		autoref_request_r <= #TCQ autoref_request;
		ref_en_r <= #TCQ autoref_en;
	end //always
	
	assign autoref_req = autoref_request_r;

endmodule
module autoref_config(
		input clk,
		input rst,
		
		input set_interval,
		input[27:0] interval_in,
		input set_trfc,
		input[27:0] trfc_in,
		
		
		output reg aref_en,
		output reg[27:0] aref_interval,
		output reg[27:0] trfc
    );
	 
	 
	 always@(posedge clk) begin
		if(rst) begin
			aref_en <= 0;
			aref_interval <= 0;
			trfc <= 0;
		end
		else begin
			if(set_interval) begin
				aref_en <= |interval_in;
				aref_interval <= interval_in;
			end //set_interval
			
			if(set_trfc) begin
				trfc <= trfc_in;
			end
		end
	 end

endmodule
module sg_list_reader_64 #(
	parameter C_DATA_WIDTH = 9'd64
)
(
	input CLK,
	input RST,

	input [C_DATA_WIDTH-1:0] BUF_DATA,	// Scatter gather buffer data 
	input BUF_DATA_EMPTY,				// Scatter gather buffer data empty
	output BUF_DATA_REN,				// Scatter gather buffer data read enable

	output VALID,						// Scatter gather element data is valid
	output EMPTY,						// Scatter gather elements empty
	input REN,							// Scatter gather element data read enable
	output [63:0] ADDR,					// Scatter gather element address
	output [31:0] LEN					// Scatter gather element length (in words)
);

(* syn_encoding = "user" *)
(* fsm_encoding = "user" *)
reg		[1:0]				rRdState=`S_SGR64_RD_0, _rRdState=`S_SGR64_RD_0;

(* syn_encoding = "user" *)
(* fsm_encoding = "user" *)
reg		[1:0]				rCapState=`S_SGR64_CAP_0, _rCapState=`S_SGR64_CAP_0;
reg		[C_DATA_WIDTH-1:0]	rData={C_DATA_WIDTH{1'd0}}, _rData={C_DATA_WIDTH{1'd0}};
reg		[63:0]				rAddr=64'd0, _rAddr=64'd0;
reg		[31:0]				rLen=0, _rLen=0;
reg							rFifoValid=0, _rFifoValid=0;
reg							rDataValid=0, _rDataValid=0;


assign BUF_DATA_REN = rRdState[0]; // Not S_SGR64_RD_WAIT
assign VALID = rCapState[1]; // S_SGR64_CAP_RDY
assign EMPTY = (BUF_DATA_EMPTY & rRdState[0]); // Not S_SGR64_RD_WAIT
assign ADDR = rAddr;
assign LEN = rLen;


// Capture address and length as it comes out of the FIFO
always @ (posedge CLK) begin
	rRdState <= #1 (RST ? `S_SGR64_RD_0 : _rRdState);
	rCapState <= #1 (RST ? `S_SGR64_CAP_0 : _rCapState);
	rData <= #1 _rData;
	rFifoValid <= #1 (RST ? 1'd0 : _rFifoValid);
	rDataValid <= #1 (RST ? 1'd0 : _rDataValid);
	rAddr <= #1 _rAddr;
	rLen <= #1 _rLen;
end

always @ (*) begin
	_rRdState = rRdState;
	_rCapState = rCapState;
	_rAddr = rAddr;
	_rLen = rLen;
	_rData = BUF_DATA;
	_rFifoValid = (BUF_DATA_REN & !BUF_DATA_EMPTY);
	_rDataValid = rFifoValid;

	case (rCapState)
	
	`S_SGR64_CAP_0: begin
		if (rDataValid) begin
			_rAddr = rData;
			_rCapState = `S_SGR64_CAP_1;
		end
	end
	
	`S_SGR64_CAP_1: begin
		if (rDataValid) begin
			_rLen = rData[31:0];
			_rCapState = `S_SGR64_CAP_RDY;
		end
	end

	`S_SGR64_CAP_RDY: begin
		if (REN)
			_rCapState = `S_SGR64_CAP_0;
	end

	default: begin
		_rCapState = `S_SGR64_CAP_0;
	end
	
	endcase

	case (rRdState)

	`S_SGR64_RD_0: begin // Read from the sg data FIFO
		if (!BUF_DATA_EMPTY)
			_rRdState = `S_SGR64_RD_1;
	end

	`S_SGR64_RD_1: begin // Read from the sg data FIFO
		if (!BUF_DATA_EMPTY)
			_rRdState = `S_SGR64_RD_WAIT;
	end

	`S_SGR64_RD_WAIT: begin // Wait for the data to be consumed
		if (REN)
			_rRdState = `S_SGR64_RD_0;
	end

	default: begin
		_rRdState = `S_SGR64_RD_0;
	end
	
	endcase
end

endmodule
module tx_engine_formatter_128 #(
	parameter C_PCI_DATA_WIDTH = 9'd128,
	// Local parameters
	parameter C_TRAFFIC_CLASS = 3'b0,
	parameter C_RELAXED_ORDER = 1'b0,
	parameter C_NO_SNOOP = 1'b0
)
(
	input CLK,
	input RST,
	input [15:0] CONFIG_COMPLETER_ID,

	input VALID,		 					// Are input parameters valid?
	input WNR,		 						// Is a write request, not a read?
	input [7:0] TAG,		 				// External tag
	input [3:0] CHNL,		 				// Internal tag (just channel portion)
	input [61:0] ADDR,		 				// Request address
	input ADDR_64,		 					// Request address is 64 bit
	input [9:0] LEN,		 				// Request length
	input LEN_ONE,		 					// Request length equals 1
	input [C_PCI_DATA_WIDTH-1:0] WR_DATA,	// Request data, timed to arrive accordingly

	output [C_PCI_DATA_WIDTH-1:0] OUT_DATA,	// Formatted PCI packet data
	output OUT_DATA_WEN 					// Write enable for formatted packet data
);

reg									rState=`S_TXENGFMTR128_IDLE, _rState=`S_TXENGFMTR128_IDLE;
reg									rAddr64=0, _rAddr64=0;
reg		[C_PCI_DATA_WIDTH-1:0]		rData={C_PCI_DATA_WIDTH{1'd0}}, _rData={C_PCI_DATA_WIDTH{1'd0}};
reg		[C_PCI_DATA_WIDTH-1:0]		rPrevData={C_PCI_DATA_WIDTH{1'd0}}, _rPrevData={C_PCI_DATA_WIDTH{1'd0}};
reg									rDataWen=0, _rDataWen=0;
reg		[9:0]						rLen=0, _rLen=0;
reg									rDone=0, _rDone=0;


assign OUT_DATA = rData;
assign OUT_DATA_WEN = rDataWen;


// Format read and write requests into PCIe packets.
wire [63:0] wHdrData = ({WR_DATA[31:0], ADDR[29:0], 2'b00, ADDR[61:30]})>>(32*(!ADDR_64));
wire [C_PCI_DATA_WIDTH-1:0] wWrData = ({WR_DATA[31:0], rPrevData})>>(32*(!rAddr64));

always @ (posedge CLK) begin
	rState <= #1 (RST ? `S_TXENGFMTR128_IDLE : _rState);
	rDataWen <= #1 (RST ? 1'd0 : _rDataWen);
	rData <= #1 _rData;
	rLen <= #1 _rLen;
	rAddr64 <= #1 _rAddr64;
	rPrevData <= #1 _rPrevData;
	rDone <= #1 _rDone;
end

always @ (*) begin
	_rState = rState;
	_rLen = rLen;
	_rData = rData;
	_rDataWen = rDataWen;
	_rPrevData = WR_DATA;
	_rAddr64 = rAddr64;
	case (rState) 

	`S_TXENGFMTR128_IDLE : begin // FIFO data should be available now (if it's a write)
		_rLen = LEN - !ADDR_64; // Subtract 1 for 32 bit (HDR has one)
		_rAddr64 = ADDR_64;
		_rData = {wHdrData,														// DW3, DW2
					CONFIG_COMPLETER_ID[15:3], 3'b0, TAG,
					(LEN_ONE ? 4'b0 : 4'b1111), 4'b1111,						// DW1
					1'b0, {WNR, ADDR_64, 5'd0}, 1'b0, C_TRAFFIC_CLASS, CHNL, 1'b0, 1'b0, // Use the reserved 4 bits before traffic class to hide the internal tag 
					C_RELAXED_ORDER, C_NO_SNOOP, 2'b0, LEN};					// DW0
		_rDataWen = VALID;
		_rDone = (LEN <= {1'b1, 1'b0, !ADDR_64});
		_rState = (VALID & WNR & (ADDR_64 | !LEN_ONE) ? `S_TXENGFMTR128_WR : `S_TXENGFMTR128_IDLE);
	end

	`S_TXENGFMTR128_WR : begin
		_rLen = rLen - 3'd4;
		_rDone = (rLen <= 4'd8);
		_rData = wWrData;
		_rState = (rDone ? `S_TXENGFMTR128_IDLE : `S_TXENGFMTR128_WR);
	end

	endcase
end

endmodule
module ff(
	CLK,
	D,
	Q
);

input 					CLK;
input 					D;
output 				Q;

reg						Q;

always @ (posedge CLK) begin 
	Q <= #1 D; 
end
	
endmodule
module syncff(
	CLK,
	IN_ASYNC,
	OUT_SYNC
);

input 					CLK;
input 					IN_ASYNC;
output 				OUT_SYNC;

wire					wSyncFFQ;

ff syncFF (
	.CLK(CLK),
	.D(IN_ASYNC),
	.Q(wSyncFFQ)
);

ff metaFF (
	.CLK(CLK),
	.D(wSyncFFQ),
	.Q(OUT_SYNC)
);
endmodule
module fifo_packer_32 (
	input CLK,
	input RST,
	input [31:0] DATA_IN,		// Incoming data
	input DATA_IN_EN,			// Incoming data enable
	input DATA_IN_DONE,			// Incoming data packet end
	input DATA_IN_ERR,			// Incoming data error
	input DATA_IN_FLUSH,		// End of incoming data
	output [31:0] PACKED_DATA,	// Outgoing data
	output PACKED_WEN,			// Outgoing data write enable
	output PACKED_DATA_DONE,	// End of outgoing data packet
	output PACKED_DATA_ERR,		// Error in outgoing data
	output PACKED_DATA_FLUSHED	// End of outgoing data
);

reg					rPackedDone=0, _rPackedDone=0;
reg					rPackedErr=0, _rPackedErr=0;
reg					rPackedFlush=0, _rPackedFlush=0;
reg					rPackedFlushed=0, _rPackedFlushed=0;
reg		[31:0]		rDataIn=64'd0, _rDataIn=64'd0;
reg					rDataInEn=0, _rDataInEn=0;


assign PACKED_DATA = rDataIn;
assign PACKED_WEN = rDataInEn;
assign PACKED_DATA_DONE = rPackedDone;
assign PACKED_DATA_ERR = rPackedErr;
assign PACKED_DATA_FLUSHED = rPackedFlushed;


// Buffers input data to ease timing.
always @ (posedge CLK) begin
	rPackedDone <= #1 (RST ? 1'd0 : _rPackedDone);
	rPackedErr <= #1 (RST ? 1'd0 : _rPackedErr);
	rPackedFlush <= #1 (RST ? 1'd0 : _rPackedFlush);
	rPackedFlushed <= #1 (RST ? 1'd0 : _rPackedFlushed);
	rDataIn <= #1 _rDataIn;
	rDataInEn <= #1 (RST ? 1'd0 : _rDataInEn);
end

always @ (*) begin
	// Buffer and mask the input data.
	_rDataIn = DATA_IN;
	_rDataInEn = DATA_IN_EN;

	// Track done/error/flush signals.
	_rPackedDone = DATA_IN_DONE;
	_rPackedErr = DATA_IN_ERR;
	_rPackedFlush = DATA_IN_FLUSH;
	_rPackedFlushed = rPackedFlush;
end



endmodule
module pcie_reset_delay_v6 # (

  parameter PL_FAST_TRAIN = "FALSE",
  parameter REF_CLK_FREQ = 0,   // 0 - 100 MHz, 1 - 125 MHz, 2 - 250 MHz
  parameter TCQ = 1

)
(

  input  wire        ref_clk,
  input  wire        sys_reset_n,
  output             delayed_sys_reset_n
   
);


  localparam         TBIT =  (PL_FAST_TRAIN == "FALSE") ?  ((REF_CLK_FREQ == 1) ? 20: (REF_CLK_FREQ == 0) ? 20 : 21) : 2;

  reg [7:0]          reg_count_7_0;
  reg [7:0]          reg_count_15_8;
  reg [7:0]          reg_count_23_16;
  wire [23:0]        concat_count;

  assign concat_count = {reg_count_23_16, reg_count_15_8, reg_count_7_0};

  always @(posedge ref_clk or negedge sys_reset_n) begin

    if (!sys_reset_n) begin

      reg_count_7_0 <= #TCQ 8'h0;
      reg_count_15_8 <= #TCQ 8'h0;
      reg_count_23_16 <= #TCQ 8'h0;

    end else begin

      if (delayed_sys_reset_n != 1'b1) begin

        reg_count_7_0   <= #TCQ reg_count_7_0 + 1'b1;
        reg_count_15_8  <= #TCQ (reg_count_7_0 == 8'hff)? reg_count_15_8  + 1'b1 : reg_count_15_8 ;
        reg_count_23_16 <= #TCQ ((reg_count_15_8 == 8'hff) & (reg_count_7_0 == 8'hff)) ? reg_count_23_16 + 1'b1 : reg_count_23_16;

      end 

    end

  end

  assign delayed_sys_reset_n = concat_count[TBIT]; 

endmodule
module tx_engine_selector #(
	parameter C_NUM_CHNL = 4'd12
)
(
	input CLK,
	input RST,

	input [C_NUM_CHNL-1:0] REQ_ALL,	// Write requests

	output REQ,						// Write request
	output [3:0] CHNL				// Write channel
);

reg		[3:0]						rReqChnl=0, _rReqChnl=0;
reg		[3:0]						rReqChnlNext=0, _rReqChnlNext=0;
reg									rReqChnlsSame=0, _rReqChnlsSame=0;
reg		[3:0]						rChnlNext=0, _rChnlNext=0;
reg		[3:0]						rChnlNextNext=0, _rChnlNextNext=0;
reg									rChnlNextDfrnt=0, _rChnlNextDfrnt=0;
reg									rChnlNextNextOn=0, _rChnlNextNextOn=0;
wire								wChnlNextNextOn = (REQ_ALL>>(rChnlNextNext));
reg									rReq=0, _rReq=0;
wire								wReq = (REQ_ALL>>(rReqChnl));
reg									rReqChnlNextUpdated=0, _rReqChnlNextUpdated=0;


assign REQ = rReq;
assign CHNL = rReqChnl;


// Search for the next request so that we can move onto it immediately after
// the current channel has released its request.
always @ (posedge CLK) begin
	rReq <= #1 (RST ? 1'd0 : _rReq);
	rReqChnl <= #1 (RST ? 4'd0 : _rReqChnl);
	rReqChnlNext <= #1 (RST ? 4'd0 : _rReqChnlNext);
	rChnlNext <= #1 (RST ? 4'd0 : _rChnlNext);
	rChnlNextNext <= #1 (RST ? 4'd0 : _rChnlNextNext);
	rChnlNextDfrnt <= #1 (RST ? 1'd0 : _rChnlNextDfrnt);
	rChnlNextNextOn <= #1 (RST ? 1'd0 : _rChnlNextNextOn);
	rReqChnlsSame <= #1 (RST ? 1'd0 : _rReqChnlsSame);
	rReqChnlNextUpdated <= #1 (RST ? 1'd1 : _rReqChnlNextUpdated);
end

always @ (*) begin
	// Go through each channel (RR), looking for requests
	_rChnlNextNextOn = wChnlNextNextOn;
	_rChnlNext = rChnlNextNext;
	_rChnlNextNext = (rChnlNextNext == C_NUM_CHNL - 1 ? 4'd0 : rChnlNextNext + 1'd1);
	_rChnlNextDfrnt = (rChnlNextNext != rReqChnl);
	_rReqChnlsSame = (rReqChnlNext == rReqChnl);

	// Save ready channel if it is not the same channel we're currently on
	if (rChnlNextNextOn & rChnlNextDfrnt & rReqChnlsSame & !rReqChnlNextUpdated) begin
		_rReqChnlNextUpdated = 1;
		_rReqChnlNext = rChnlNext;
	end
	else begin
		_rReqChnlNextUpdated = 0;
		_rReqChnlNext = rReqChnlNext;
	end
	
	// Assign the new channel
	_rReq = wReq;
	_rReqChnl = (!rReq ? rReqChnlNext : rReqChnl);
end


endmodule
module ram_2clk_1w_1r (
	CLKA,
	ADDRA,
	WEA,
	DINA,
	CLKB,
	ADDRB,
	DOUTB
);

`include "common_functions.v"

parameter C_RAM_WIDTH = 32;
parameter C_RAM_DEPTH = 1024;
//Local parameters
parameter C_RAM_ADDR_BITS = clog2s(C_RAM_DEPTH);

input							CLKA;
input							CLKB;
input 							WEA;
input 	[C_RAM_ADDR_BITS-1:0]	ADDRA;
input 	[C_RAM_ADDR_BITS-1:0]	ADDRB;
input 	[C_RAM_WIDTH-1:0]		DINA;
output 	[C_RAM_WIDTH-1:0]		DOUTB;

reg [C_RAM_WIDTH-1:0] rRAM [C_RAM_DEPTH-1:0];
reg [C_RAM_WIDTH-1:0] rDout;   

assign DOUTB = rDout;

always @(posedge CLKA) begin
  if (WEA)
	 rRAM[ADDRA] <= #1 DINA;
end

always @(posedge CLKB) begin
  rDout <= #1 rRAM[ADDRB];
end
						
endmodule
module sg_list_reader_32 #(
	parameter C_DATA_WIDTH = 9'd32
)
(
	input CLK,
	input RST,

	input [C_DATA_WIDTH-1:0] BUF_DATA,	// Scatter gather buffer data 
	input BUF_DATA_EMPTY,				// Scatter gather buffer data empty
	output BUF_DATA_REN,				// Scatter gather buffer data read enable

	output VALID,						// Scatter gather element data is valid
	output EMPTY,						// Scatter gather elements empty
	input REN,							// Scatter gather element data read enable
	output [63:0] ADDR,					// Scatter gather element address
	output [31:0] LEN					// Scatter gather element length (in words)
);

(* syn_encoding = "user" *)
(* fsm_encoding = "user" *)
reg		[2:0]				rRdState=`S_SGR32_RD_0, _rRdState=`S_SGR32_RD_0;

(* syn_encoding = "user" *)
(* fsm_encoding = "user" *)
reg		[2:0]				rCapState=`S_SGR32_CAP_0, _rCapState=`S_SGR32_CAP_0;
reg		[C_DATA_WIDTH-1:0]	rData={C_DATA_WIDTH{1'd0}}, _rData={C_DATA_WIDTH{1'd0}};
reg		[63:0]				rAddr=64'd0, _rAddr=64'd0;
reg		[31:0]				rLen=0, _rLen=0;
reg							rFifoValid=0, _rFifoValid=0;
reg							rDataValid=0, _rDataValid=0;


assign BUF_DATA_REN = !rRdState[2]; // Not S_SGR32_RD_0
assign VALID = rCapState[2]; // S_SGR32_CAP_RDY
assign EMPTY = (BUF_DATA_EMPTY & !rRdState[2]); // Not S_SGR32_RD_0
assign ADDR = rAddr;
assign LEN = rLen;


// Capture address and length as it comes out of the FIFO
always @ (posedge CLK) begin
	rRdState <= #1 (RST ? `S_SGR32_RD_0 : _rRdState);
	rCapState <= #1 (RST ? `S_SGR32_CAP_0 : _rCapState);
	rData <= #1 _rData;
	rFifoValid <= #1 (RST ? 1'd0 : _rFifoValid);
	rDataValid <= #1 (RST ? 1'd0 : _rDataValid);
	rAddr <= #1 _rAddr;
	rLen <= #1 _rLen;
end

always @ (*) begin
	_rRdState = rRdState;
	_rCapState = rCapState;
	_rAddr = rAddr;
	_rLen = rLen;
	_rData = BUF_DATA;
	_rFifoValid = (BUF_DATA_REN & !BUF_DATA_EMPTY);
	_rDataValid = rFifoValid;

	case (rCapState)
	
	`S_SGR32_CAP_0: begin
		if (rDataValid) begin
			_rAddr[31:0] = rData;
			_rCapState = `S_SGR32_CAP_1;
		end
	end

	`S_SGR32_CAP_1: begin
		if (rDataValid) begin
			_rAddr[63:32] = rData;
			_rCapState = `S_SGR32_CAP_2;
		end
	end
	
	`S_SGR32_CAP_2: begin
		if (rDataValid) begin
			_rLen = rData;
			_rCapState = `S_SGR32_CAP_3;
		end
	end

	`S_SGR32_CAP_3: begin
		if (rDataValid)
			_rCapState = `S_SGR32_CAP_RDY;
	end

	`S_SGR32_CAP_RDY: begin
		if (REN)
			_rCapState = `S_SGR32_CAP_0;
	end

	default: begin
		_rCapState = `S_SGR32_CAP_0;
	end
	
	endcase

	case (rRdState)

	`S_SGR32_RD_0: begin // Read from the sg data FIFO
		if (!BUF_DATA_EMPTY)
			_rRdState = `S_SGR32_RD_1;
	end

	`S_SGR32_RD_1: begin // Read from the sg data FIFO
		if (!BUF_DATA_EMPTY)
			_rRdState = `S_SGR32_RD_2;
	end

	`S_SGR32_RD_2: begin // Read from the sg data FIFO
		if (!BUF_DATA_EMPTY)
			_rRdState = `S_SGR32_RD_3;
	end

	`S_SGR32_RD_3: begin // Read from the sg data FIFO
		if (!BUF_DATA_EMPTY)
			_rRdState = `S_SGR32_RD_WAIT;
	end

	`S_SGR32_RD_WAIT: begin // Wait for the data to be consumed
		if (REN)
			_rRdState = `S_SGR32_RD_0;
	end

	default: begin
		_rRdState = `S_SGR32_RD_0;
	end
	
	endcase
end

endmodule
module cross_domain_signal (
	input CLK_A,		// Clock for domain A
	input CLK_A_SEND,	// Signal from domain A to domain B
	output CLK_A_RECV,	// Signal from domain B received in domain A 
	input CLK_B,		// Clock for domain B
	output CLK_B_RECV,	// Signal from domain A received in domain B
	input CLK_B_SEND	// Signal from domain B to domain A
);


// Sync level signals across domains.
syncff sigAtoB (.CLK(CLK_B), .IN_ASYNC(CLK_A_SEND), .OUT_SYNC(CLK_B_RECV));
syncff sigBtoA (.CLK(CLK_A), .IN_ASYNC(CLK_B_SEND), .OUT_SYNC(CLK_A_RECV));


endmodule
module fifo_packer_64 (
	input CLK,
	input RST,
	input [63:0] DATA_IN,		// Incoming data
	input [1:0] DATA_IN_EN,		// Incoming data enable
	input DATA_IN_DONE,			// Incoming data packet end
	input DATA_IN_ERR,			// Incoming data error
	input DATA_IN_FLUSH,		// End of incoming data
	output [63:0] PACKED_DATA,	// Outgoing data
	output PACKED_WEN,			// Outgoing data write enable
	output PACKED_DATA_DONE,	// End of outgoing data packet
	output PACKED_DATA_ERR,		// Error in outgoing data
	output PACKED_DATA_FLUSHED	// End of outgoing data
);

reg		[1:0]		rPackedCount=0, _rPackedCount=0;
reg					rPackedDone=0, _rPackedDone=0;
reg					rPackedErr=0, _rPackedErr=0;
reg					rPackedFlush=0, _rPackedFlush=0;
reg					rPackedFlushed=0, _rPackedFlushed=0;
reg		[95:0]		rPackedData=96'd0, _rPackedData=96'd0;
reg		[63:0]		rDataIn=64'd0, _rDataIn=64'd0;
reg		[1:0]		rDataInEn=0, _rDataInEn=0;
reg		[63:0]		rDataMasked=64'd0, _rDataMasked=64'd0;
reg		[1:0]		rDataMaskedEn=0, _rDataMaskedEn=0;


assign PACKED_DATA = rPackedData[63:0];
assign PACKED_WEN = rPackedCount[1];
assign PACKED_DATA_DONE = rPackedDone;
assign PACKED_DATA_ERR = rPackedErr;
assign PACKED_DATA_FLUSHED = rPackedFlushed;


// Buffers input data until 2 words are available, then writes 2 words out.
wire [63:0] wMask = {64{1'b1}}<<(32*rDataInEn);
wire [63:0]	wDataMasked = ~wMask & rDataIn;
always @ (posedge CLK) begin
	rPackedCount <= #1 (RST ? 2'd0 : _rPackedCount);
	rPackedDone <= #1 (RST ? 1'd0 : _rPackedDone);
	rPackedErr <= #1 (RST ? 1'd0 : _rPackedErr);
	rPackedFlush <= #1 (RST ? 1'd0 : _rPackedFlush);
	rPackedFlushed <= #1 (RST ? 1'd0 : _rPackedFlushed);
	rPackedData <= #1 (RST ? 96'd0 : _rPackedData);
	rDataIn <= #1 _rDataIn;
	rDataInEn <= #1 (RST ? 2'd0 : _rDataInEn);
	rDataMasked <= #1 _rDataMasked;
	rDataMaskedEn <= #1 (RST ? 2'd0 : _rDataMaskedEn);
end

always @ (*) begin
	// Buffer and mask the input data.
	_rDataIn = DATA_IN;
	_rDataInEn = DATA_IN_EN;
	_rDataMasked = wDataMasked;
	_rDataMaskedEn = rDataInEn;

	// Count what's in our buffer. When we reach 2 words, 2 words will be written
	// out. If flush is requested, write out whatever remains.
	if (rPackedFlush && rPackedCount[0])
		_rPackedCount = 2;
	else
		_rPackedCount = rPackedCount + rDataMaskedEn - {rPackedCount[1], 1'd0};
	
	// Shift data into and out of our buffer as we receive and write out data.
	if (rDataMaskedEn != 2'd0)
		_rPackedData = ((rPackedData>>(32*{rPackedCount[1], 1'd0})) | (rDataMasked<<(32*rPackedCount[0])));
	else
		_rPackedData = (rPackedData>>(32*{rPackedCount[1], 1'd0}));

	// Track done/error/flush signals.
	_rPackedDone = DATA_IN_DONE;
	_rPackedErr = DATA_IN_ERR;
	_rPackedFlush = DATA_IN_FLUSH;
	_rPackedFlushed = rPackedFlush;
end



endmodule
module sg_list_reader_128 #(
	parameter C_DATA_WIDTH = 9'd128
)
(
	input CLK,
	input RST,

	input [C_DATA_WIDTH-1:0] BUF_DATA,	// Scatter gather buffer data 
	input BUF_DATA_EMPTY,				// Scatter gather buffer data empty
	output BUF_DATA_REN,				// Scatter gather buffer data read enable

	output VALID,						// Scatter gather element data is valid
	output EMPTY,						// Scatter gather elements empty
	input REN,							// Scatter gather element data read enable
	output [63:0] ADDR,					// Scatter gather element address
	output [31:0] LEN					// Scatter gather element length (in words)
);

(* syn_encoding = "user" *)
(* fsm_encoding = "user" *)
reg							rRdState=`S_SGR128_RD_0, _rRdState=`S_SGR128_RD_0;

(* syn_encoding = "user" *)
(* fsm_encoding = "user" *)
reg							rCapState=`S_SGR128_CAP_0, _rCapState=`S_SGR128_CAP_0;
reg		[C_DATA_WIDTH-1:0]	rData={C_DATA_WIDTH{1'd0}}, _rData={C_DATA_WIDTH{1'd0}};
reg		[63:0]				rAddr=64'd0, _rAddr=64'd0;
reg		[31:0]				rLen=0, _rLen=0;
reg							rFifoValid=0, _rFifoValid=0;
reg							rDataValid=0, _rDataValid=0;


assign BUF_DATA_REN = rRdState; // Not S_SGR128_RD_WAIT
assign VALID = rCapState; // S_SGR128_CAP_RDY
assign EMPTY = (BUF_DATA_EMPTY & rRdState); // Not S_SGR128_RD_WAIT
assign ADDR = rAddr;
assign LEN = rLen;


// Capture address and length as it comes out of the FIFO
always @ (posedge CLK) begin
	rRdState <= #1 (RST ? `S_SGR128_RD_0 : _rRdState);
	rCapState <= #1 (RST ? `S_SGR128_CAP_0 : _rCapState);
	rData <= #1 _rData;
	rFifoValid <= #1 (RST ? 1'd0 : _rFifoValid);
	rDataValid <= #1 (RST ? 1'd0 : _rDataValid);
	rAddr <= #1 _rAddr;
	rLen <= #1 _rLen;
end

always @ (*) begin
	_rRdState = rRdState;
	_rCapState = rCapState;
	_rAddr = rAddr;
	_rLen = rLen;
	_rData = BUF_DATA;
	_rFifoValid = (BUF_DATA_REN & !BUF_DATA_EMPTY);
	_rDataValid = rFifoValid;

	case (rCapState)
	
	`S_SGR128_CAP_0: begin
		if (rDataValid) begin
			_rAddr = rData[63:0];
			_rLen = rData[95:64];
			_rCapState = `S_SGR128_CAP_RDY;
		end
	end

	`S_SGR128_CAP_RDY: begin
		if (REN)
			_rCapState = `S_SGR128_CAP_0;
	end
	
	endcase

	case (rRdState)

	`S_SGR128_RD_0: begin // Read from the sg data FIFO
		if (!BUF_DATA_EMPTY)
			_rRdState = `S_SGR128_RD_WAIT;
	end

	`S_SGR128_RD_WAIT: begin // Wait for the data to be consumed
		if (REN)
			_rRdState = `S_SGR128_RD_0;
	end
	
	endcase
end

endmodule
module async_fifo #(
	parameter C_WIDTH = 32,	// Data bus width
	parameter C_DEPTH = 1024,	// Depth of the FIFO
	// Local parameters
	parameter C_REAL_DEPTH = 2**clog2(C_DEPTH),
	parameter C_DEPTH_BITS = clog2(C_REAL_DEPTH),
	parameter C_DEPTH_P1_BITS = clog2(C_REAL_DEPTH+1)
)
(
	input RD_CLK,							// Read clock
	input RD_RST,							// Read synchronous reset
	input WR_CLK,						 	// Write clock
	input WR_RST,							// Write synchronous reset
	input [C_WIDTH-1:0] WR_DATA, 			// Write data input (WR_CLK)
	input WR_EN, 							// Write enable, high active (WR_CLK)
	output [C_WIDTH-1:0] RD_DATA, 			// Read data output (RD_CLK)
	input RD_EN,							// Read enable, high active (RD_CLK)
	output WR_FULL, 						// Full condition (WR_CLK)
	output RD_EMPTY 						// Empty condition (RD_CLK)
);

`include "common_functions.v"

wire						wCmpEmpty;
wire						wCmpFull;
wire	[C_DEPTH_BITS-1:0]	wWrPtr;
wire	[C_DEPTH_BITS-1:0]	wRdPtr;
wire	[C_DEPTH_BITS-1:0]	wWrPtrP1;
wire	[C_DEPTH_BITS-1:0]	wRdPtrP1;


// Memory block (synthesis attributes applied to this module will
// determine the memory option).
ram_2clk_1w_1r #(.C_RAM_WIDTH(C_WIDTH), .C_RAM_DEPTH(C_REAL_DEPTH)) mem (
	.CLKA(WR_CLK),
	.ADDRA(wWrPtr),
	.WEA(WR_EN & !WR_FULL),
	.DINA(WR_DATA),
	.CLKB(RD_CLK),
	.ADDRB(wRdPtr),
	.DOUTB(RD_DATA)
);


// Compare the pointers.
async_cmp #(.C_DEPTH_BITS(C_DEPTH_BITS)) asyncCompare (
	.WR_RST(WR_RST),
	.WR_CLK(WR_CLK),
	.RD_RST(RD_RST),
	.RD_CLK(RD_CLK),
	.RD_VALID(RD_EN & !RD_EMPTY),
	.WR_VALID(WR_EN & !WR_FULL),
	.EMPTY(wCmpEmpty), 
	.FULL(wCmpFull),
	.WR_PTR(wWrPtr), 
	.WR_PTR_P1(wWrPtrP1), 
	.RD_PTR(wRdPtr), 
	.RD_PTR_P1(wRdPtrP1)
);


// Calculate empty
rd_ptr_empty #(.C_DEPTH_BITS(C_DEPTH_BITS)) rdPtrEmpty (
	.RD_EMPTY(RD_EMPTY), 
	.RD_PTR(wRdPtr),
	.RD_PTR_P1(wRdPtrP1),
	.CMP_EMPTY(wCmpEmpty), 
	.RD_EN(RD_EN),
	.RD_CLK(RD_CLK), 
	.RD_RST(RD_RST)
);


// Calculate full
wr_ptr_full #(.C_DEPTH_BITS(C_DEPTH_BITS)) wrPtrFull (
	.WR_CLK(WR_CLK), 
	.WR_RST(WR_RST),
	.WR_EN(WR_EN),
	.WR_FULL(WR_FULL), 
	.WR_PTR(wWrPtr),
	.WR_PTR_P1(wWrPtrP1),
	.CMP_FULL(wCmpFull)
);
 
endmodule
module async_cmp #(
  parameter C_DEPTH_BITS = 4,
  // Local parameters
  parameter N = C_DEPTH_BITS-1
)
(
	input WR_RST,
	input WR_CLK,
	input RD_RST,
	input RD_CLK,
	input RD_VALID,
	input WR_VALID,
	output EMPTY, 
	output FULL, 
	input [C_DEPTH_BITS-1:0] WR_PTR, 
	input [C_DEPTH_BITS-1:0] RD_PTR, 
	input [C_DEPTH_BITS-1:0] WR_PTR_P1, 
	input [C_DEPTH_BITS-1:0] RD_PTR_P1
);
  
reg				rDir=0;
wire			wDirSet = (  (WR_PTR[N]^RD_PTR[N-1]) & ~(WR_PTR[N-1]^RD_PTR[N]));
wire			wDirClr = ((~(WR_PTR[N]^RD_PTR[N-1]) &  (WR_PTR[N-1]^RD_PTR[N])) | WR_RST);

reg				rRdValid=0;
reg				rEmpty=1;
reg				rFull=0;
wire			wATBEmpty = ((WR_PTR == RD_PTR_P1) && (RD_VALID | rRdValid));
wire			wATBFull = ((WR_PTR_P1 == RD_PTR) && WR_VALID);
wire			wEmpty = ((WR_PTR == RD_PTR) && !rDir);
wire			wFull = ((WR_PTR == RD_PTR) && rDir);

assign EMPTY = wATBEmpty || rEmpty;
assign FULL  = wATBFull || rFull;

always @(posedge wDirSet or posedge wDirClr)
if (wDirClr) 
	rDir <= 1'b0;
else
	rDir <= 1'b1;

always @(posedge RD_CLK) begin
	rEmpty <= (RD_RST ? 1'd1 : wEmpty);
	rRdValid <= (RD_RST ? 1'd0 : RD_VALID);
end

always @(posedge WR_CLK) begin
	rFull <= (WR_RST ? 1'd0 : wFull);
end

endmodule
module rd_ptr_empty #(
	parameter C_DEPTH_BITS = 4
)
(
	input RD_CLK, 
	input RD_RST,
	input RD_EN, 
	output RD_EMPTY,
	output [C_DEPTH_BITS-1:0] RD_PTR,
	output [C_DEPTH_BITS-1:0] RD_PTR_P1,
	input CMP_EMPTY 
);

reg							rEmpty=1;
reg							rEmpty2=1;
reg		[C_DEPTH_BITS-1:0]	rRdPtr=0;
reg		[C_DEPTH_BITS-1:0]	rRdPtrP1=0;
reg		[C_DEPTH_BITS-1:0]	rBin=0;
reg		[C_DEPTH_BITS-1:0]	rBinP1=1;
wire	[C_DEPTH_BITS-1:0]	wGrayNext;
wire	[C_DEPTH_BITS-1:0]	wGrayNextP1;
wire	[C_DEPTH_BITS-1:0]	wBinNext;
wire	[C_DEPTH_BITS-1:0]	wBinNextP1;

assign RD_EMPTY = rEmpty;
assign RD_PTR = rRdPtr;
assign RD_PTR_P1 = rRdPtrP1;

// Gray coded pointer
always @(posedge RD_CLK or posedge RD_RST) begin
	if (RD_RST) begin
		rBin <= #1 0;
		rBinP1 <= #1 1;
		rRdPtr <= #1 0;
		rRdPtrP1 <= #1 0;
	end
	else begin
		rBin <= #1 wBinNext;
		rBinP1 <= #1 wBinNextP1;
		rRdPtr <= #1 wGrayNext;
		rRdPtrP1 <= #1 wGrayNextP1;
	end
end

// Increment the binary count if not empty
assign wBinNext = (!rEmpty ? rBin + RD_EN : rBin);
assign wBinNextP1 = (!rEmpty ? rBinP1 + RD_EN : rBinP1);
assign wGrayNext = ((wBinNext>>1) ^ wBinNext); // binary-to-gray conversion
assign wGrayNextP1 = ((wBinNextP1>>1) ^ wBinNextP1); // binary-to-gray conversion

always @(posedge RD_CLK) begin
	if (CMP_EMPTY)
		{rEmpty, rEmpty2} <= #1 2'b11;
	else
		{rEmpty, rEmpty2} <= #1 {rEmpty2, CMP_EMPTY};
end

endmodule
module wr_ptr_full #(
	parameter C_DEPTH_BITS = 4
)
(
	input WR_CLK, 
	input WR_RST,
	input WR_EN,
	output WR_FULL, 
	output [C_DEPTH_BITS-1:0] WR_PTR, 
	output [C_DEPTH_BITS-1:0] WR_PTR_P1, 
	input CMP_FULL
);

reg							rFull=0;
reg							rFull2=0;
reg		[C_DEPTH_BITS-1:0]	rPtr=0;
reg		[C_DEPTH_BITS-1:0]	rPtrP1=0;
reg		[C_DEPTH_BITS-1:0]	rBin=0;
reg		[C_DEPTH_BITS-1:0]	rBinP1=1;
wire	[C_DEPTH_BITS-1:0]	wGrayNext;
wire	[C_DEPTH_BITS-1:0]	wGrayNextP1;
wire	[C_DEPTH_BITS-1:0]	wBinNext;
wire	[C_DEPTH_BITS-1:0]	wBinNextP1;

assign WR_FULL = rFull;
assign WR_PTR = rPtr;
assign WR_PTR_P1 = rPtrP1;

// Gray coded pointer
always @(posedge WR_CLK or posedge WR_RST) begin
	if (WR_RST) begin
		rBin <= #1 0;
		rBinP1 <= #1 1;
		rPtr <= #1 0;
		rPtrP1 <= #1 0;
	end
	else begin
		rBin <= #1 wBinNext;
		rBinP1 <= #1 wBinNextP1;
		rPtr <= #1 wGrayNext;
		rPtrP1 <= #1 wGrayNextP1;
	end
end

// Increment the binary count if not full
assign wBinNext = (!rFull ? rBin + WR_EN : rBin);
assign wBinNextP1 = (!rFull ? rBinP1 + WR_EN : rBinP1);
assign wGrayNext = ((wBinNext>>1) ^ wBinNext); // binary-to-gray conversion
assign wGrayNextP1 = ((wBinNextP1>>1) ^ wBinNextP1); // binary-to-gray conversion

always @(posedge WR_CLK) begin
	if (WR_RST) 
		{rFull, rFull2} <= #1 2'b00;
	else if (CMP_FULL) 
		{rFull, rFull2} <= #1 2'b11;
	else
		{rFull, rFull2} <= #1 {rFull2, CMP_FULL};
end

endmodule
module interrupt_controller (
	input CLK,						// System clock
	input RST,						// Async reset
	input INTR,						// Pulsed high to request an interrupt
	input INTR_LEGACY_CLR,			// Pulsed high to ack the legacy interrupt and clear it
	output INTR_DONE,				// Pulsed high to signal interrupt sent
	input CONFIG_INTERRUPT_MSIENABLE,	// 1 if MSI interrupts are enable, 0 if only legacy are supported
	output CFG_INTERRUPT_ASSERT,	// Legacy interrupt message type
	input INTR_MSI_RDY,		// High when interrupt is able to be sent
	output INTR_MSI_REQUEST			// High to request interrupt, when both INTR_MSI_RDY and INTR_MSI_REQUEST are high, interrupt is sent
);

reg		[2:0]	rState=`S_INTRCTLR_IDLE;
reg		[2:0]	rStateNext=`S_INTRCTLR_IDLE;
reg				rIntr=0;
reg				rIntrAssert=0;

assign INTR_DONE = (rState == `S_INTRCLTR_DONE);
assign INTR_MSI_REQUEST = rIntr;
assign CFG_INTERRUPT_ASSERT = rIntrAssert;

// Control sending interrupts.
always @(*) begin
	case (rState)

	`S_INTRCTLR_IDLE : begin
		if (INTR) begin
			rIntr = 1;
			rIntrAssert = !CONFIG_INTERRUPT_MSIENABLE;
			rStateNext = (INTR_MSI_RDY ? `S_INTRCLTR_COMPLETE : `S_INTRCLTR_WORKING);
		end 
		else begin
			rIntr = 0;
			rIntrAssert = 0;
			rStateNext = `S_INTRCTLR_IDLE;
		end
	end

	`S_INTRCLTR_WORKING : begin
		rIntr = 1;
		rIntrAssert = !CONFIG_INTERRUPT_MSIENABLE;
		rStateNext = (INTR_MSI_RDY ? `S_INTRCLTR_COMPLETE : `S_INTRCLTR_WORKING);
	end

	`S_INTRCLTR_COMPLETE : begin
		rIntr = 0;
		rIntrAssert = !CONFIG_INTERRUPT_MSIENABLE;
		rStateNext = (CONFIG_INTERRUPT_MSIENABLE ? `S_INTRCLTR_DONE : `S_INTRCLTR_CLEAR_LEGACY);
	end

	`S_INTRCLTR_CLEAR_LEGACY : begin
		if (INTR_LEGACY_CLR) begin
			rIntr = 1;
			rIntrAssert = 0;
			rStateNext = (INTR_MSI_RDY ? `S_INTRCLTR_DONE : `S_INTRCLTR_CLEARING_LEGACY);
		end 
		else begin
			rIntr = 0;
			rIntrAssert = 1;
			rStateNext = `S_INTRCLTR_CLEAR_LEGACY;
		end
	end

	`S_INTRCLTR_CLEARING_LEGACY : begin
		rIntr = 1;
		rIntrAssert = 0;
		rStateNext = (INTR_MSI_RDY ? `S_INTRCLTR_DONE : `S_INTRCLTR_CLEARING_LEGACY);
	end

	`S_INTRCLTR_DONE : begin
		rIntr = 0;
		rIntrAssert = 0;
		rStateNext = `S_INTRCTLR_IDLE;
	end
	
	default: begin
		rIntr = 0;
		rIntrAssert = 0;
		rStateNext = `S_INTRCTLR_IDLE;
	end
	
	endcase
end

// Update the state.
always @(posedge CLK) begin
	if (RST)
		rState <= #1 `S_INTRCTLR_IDLE;
	else
		rState <= #1 rStateNext;
end

endmodule
module fifo_packer_128 (
	input CLK,
	input RST,
	input [127:0] DATA_IN,		// Incoming data
	input [2:0] DATA_IN_EN,		// Incoming data enable
	input DATA_IN_DONE,			// Incoming data packet end
	input DATA_IN_ERR,			// Incoming data error
	input DATA_IN_FLUSH,		// End of incoming data
	output [127:0] PACKED_DATA,	// Outgoing data
	output PACKED_WEN,			// Outgoing data write enable
	output PACKED_DATA_DONE,	// End of outgoing data packet
	output PACKED_DATA_ERR,		// Error in outgoing data
	output PACKED_DATA_FLUSHED	// End of outgoing data
);

reg		[2:0]		rPackedCount=0, _rPackedCount=0;
reg					rPackedDone=0, _rPackedDone=0;
reg					rPackedErr=0, _rPackedErr=0;
reg					rPackedFlush=0, _rPackedFlush=0;
reg					rPackedFlushed=0, _rPackedFlushed=0;
reg		[223:0]		rPackedData=224'd0, _rPackedData=224'd0;
reg		[127:0]		rDataIn=128'd0, _rDataIn=128'd0;
reg		[2:0]		rDataInEn=0, _rDataInEn=0;
reg		[127:0]		rDataMasked=128'd0, _rDataMasked=128'd0;
reg		[2:0]		rDataMaskedEn=0, _rDataMaskedEn=0;


assign PACKED_DATA = rPackedData[127:0];
assign PACKED_WEN = rPackedCount[2];
assign PACKED_DATA_DONE = rPackedDone;
assign PACKED_DATA_ERR = rPackedErr;
assign PACKED_DATA_FLUSHED = rPackedFlushed;


// Buffers input data until 4 words are available, then writes 4 words out.
wire [127:0] wMask = {128{1'b1}}<<(32*rDataInEn);
wire [127:0] wDataMasked = ~wMask & rDataIn;
always @ (posedge CLK) begin
	rPackedCount <= #1 (RST ? 3'd0 : _rPackedCount);
	rPackedDone <= #1 (RST ? 1'd0 : _rPackedDone);
	rPackedErr <= #1 (RST ? 1'd0 : _rPackedErr);
	rPackedFlush <= #1 (RST ? 1'd0 : _rPackedFlush);
	rPackedFlushed <= #1 (RST ? 1'd0 : _rPackedFlushed);
	rPackedData <= #1 (RST ? 224'd0 : _rPackedData);
	rDataIn <= #1 _rDataIn;
	rDataInEn <= #1 (RST ? 3'd0 : _rDataInEn);
	rDataMasked <= #1 _rDataMasked;
	rDataMaskedEn <= #1 (RST ? 3'd0 : _rDataMaskedEn);
end

always @ (*) begin
	// Buffer and mask the input data.
	_rDataIn = DATA_IN;
	_rDataInEn = DATA_IN_EN;
	_rDataMasked = wDataMasked;
	_rDataMaskedEn = rDataInEn;

	// Count what's in our buffer. When we reach 4 words, 4 words will be written
	// out. If flush is requested, write out whatever remains.
	if (rPackedFlush && (rPackedCount[1] | rPackedCount[0]))
		_rPackedCount = 4;
	else
		_rPackedCount = rPackedCount + rDataMaskedEn - {rPackedCount[2], 2'd0};
	
	// Shift data into and out of our buffer as we receive and write out data.
	if (rDataMaskedEn != 3'd0)
		_rPackedData = ((rPackedData>>(32*{rPackedCount[2], 2'd0})) | (rDataMasked<<(32*rPackedCount[1:0])));
	else
		_rPackedData = (rPackedData>>(32*{rPackedCount[2], 2'd0}));

	// Track done/error/flush signals.
	_rPackedDone = DATA_IN_DONE;
	_rPackedErr = DATA_IN_ERR;
	_rPackedFlush = DATA_IN_FLUSH;
	_rPackedFlushed = rPackedFlush;
end



endmodule
module recv_credit_flow_ctrl
  (
   input 	CLK,
   input 	RST,
   input [2:0] 	CONFIG_MAX_READ_REQUEST_SIZE, // Maximum read payload: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B
   input [11:0] CONFIG_MAX_CPL_DATA, // Receive credit limit for data
   input [7:0] 	CONFIG_MAX_CPL_HDR, // Receive credit limit for headers
   input 	CONFIG_CPL_BOUNDARY_SEL, // Read completion boundary (0=64 bytes, 1=128 bytes)w
   input 	RX_ENG_RD_DONE, // Read completed
   input 	TX_ENG_RD_REQ_SENT, // Read completion request issued
   output 	RXBUF_SPACE_AVAIL // High if enough read completion credits exist to make a read completion request
   );

   reg 		rCreditAvail=0;
   reg 		rCplDAvail=0;
   reg 		rCplHAvail=0;
   reg [12:0] 	rMaxRecv=0;
   reg [11:0] 	rCplDAmt=0;
   reg [7:0] 	rCplHAmt=0;
   reg [11:0] 	rCplD=0;
   reg [7:0] 	rCplH=0;

   assign RXBUF_SPACE_AVAIL = rCreditAvail;

   // Determine the completions required for a max read completion request.
   always @(posedge CLK) begin
      rMaxRecv <= #1 (13'd128<<CONFIG_MAX_READ_REQUEST_SIZE);
      rCplHAmt <= #1 (rMaxRecv>>({2'b11, CONFIG_CPL_BOUNDARY_SEL}));
      rCplDAmt <= #1 (rMaxRecv>>4);
      rCplHAvail <= #1 (rCplH <= CONFIG_MAX_CPL_HDR);
      rCplDAvail <= #1 (rCplD <= CONFIG_MAX_CPL_DATA);
      rCreditAvail <= #1 (rCplHAvail & rCplDAvail);
   end

   // Count the number of outstanding read completion requests.
   always @ (posedge CLK) begin
      if (RST) begin
	 rCplH <= #1 0;
	 rCplD <= #1 0;
      end
      else if (RX_ENG_RD_DONE & TX_ENG_RD_REQ_SENT) begin
	 rCplH <= #1 rCplH;
	 rCplD <= #1 rCplD;
      end
      else if (TX_ENG_RD_REQ_SENT) begin
	 rCplH <= #1 rCplH + rCplHAmt;
	 rCplD <= #1 rCplD + rCplDAmt;
      end
      else if (RX_ENG_RD_DONE) begin
	 rCplH <= #1 rCplH - rCplHAmt;
	 rCplD <= #1 rCplD - rCplDAmt;
      end
   end

endmodule
module tx_port_buffer_32 #(
	parameter C_FIFO_DATA_WIDTH = 9'd32,
	parameter C_FIFO_DEPTH = 512,
	// Local parameters
	parameter C_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_FIFO_DEPTH))+1)
)
(
	input RST,
	input CLK,

	input [C_FIFO_DATA_WIDTH-1:0] WR_DATA,		// Input data
	input WR_EN,								// Input data write enable
	output [C_FIFO_DEPTH_WIDTH-1:0] WR_COUNT,	// Input data FIFO is full

	output [C_FIFO_DATA_WIDTH-1:0] RD_DATA,		// Output data
	input RD_EN									// Output data read enable
);

`include "common_functions.v"

reg 								rFifoRdEn=0, _rFifoRdEn=0;
reg		[C_FIFO_DATA_WIDTH-1:0]		rFifoData={C_FIFO_DATA_WIDTH{1'd0}}, _rFifoData={C_FIFO_DATA_WIDTH{1'd0}};
wire	[C_FIFO_DATA_WIDTH-1:0]		wFifoData;

assign RD_DATA = rFifoData;


// Buffer the input signals that come from outside the tx_port.
always @ (posedge CLK) begin
	rFifoRdEn <= #1 (RST ? 1'd0 : _rFifoRdEn);
end

always @ (*) begin
	_rFifoRdEn = RD_EN;
end


// FIFO for storing data from the channel.
(* RAM_STYLE="BLOCK" *)
sync_fifo #(.C_WIDTH(C_FIFO_DATA_WIDTH), .C_DEPTH(C_FIFO_DEPTH), .C_PROVIDE_COUNT(1)) fifo (
	.CLK(CLK),
	.RST(RST),
	.WR_EN(WR_EN),
	.WR_DATA(WR_DATA),
	.FULL(),
	.COUNT(WR_COUNT),
	.RD_EN(rFifoRdEn),
	.RD_DATA(wFifoData),
	.EMPTY()
);


// Buffer data from the FIFO.
always @ (posedge CLK) begin
	rFifoData <= #1 _rFifoData;
end

always @ (*) begin
	_rFifoData = wFifoData;
end


endmodule
module clkgen(input wire clkin, input wire clk25m_on, output wire clkout, output wire [3:0] clk25m, output wire locked);
//reg cnt ;

wire clkout_div ;
//always @ ( posedge clkout )
//	cnt <= ~cnt ;
//assign clk25m = cnt ;
//assign clk25m = clkout_div ;
ODDR2 ODDR2_inst0 (
   .Q (clk25m[0]),   // 1-bit DDR output data
   .C0(clkout_div),   // 1-bit clock input
   .C1(~clkout_div),   // 1-bit clock input
   .CE(clk25m_on),//(1), // 1-bit clock enable input
   .D0(0), // 1-bit data input (associated with C0)
   .D1(1), // 1-bit data input (associated with C1)
   .R (0),   // 1-bit reset input
   .S (0)    // 1-bit set input
);
ODDR2 ODDR2_inst1 (
   .Q (clk25m[1]),   // 1-bit DDR output data
   .C0(clkout_div),   // 1-bit clock input
   .C1(~clkout_div),   // 1-bit clock input
   .CE(clk25m_on),//(1), // 1-bit clock enable input
   .D0(0), // 1-bit data input (associated with C0)
   .D1(1), // 1-bit data input (associated with C1)
   .R (0),   // 1-bit reset input
   .S (0)    // 1-bit set input
);
ODDR2 ODDR2_inst2 (
   .Q (clk25m[2]),   // 1-bit DDR output data
   .C0(clkout_div),   // 1-bit clock input
   .C1(~clkout_div),   // 1-bit clock input
   .CE(clk25m_on),//(1), // 1-bit clock enable input
   .D0(0), // 1-bit data input (associated with C0)
   .D1(1), // 1-bit data input (associated with C1)
   .R (0),   // 1-bit reset input
   .S (0)    // 1-bit set input
);
ODDR2 ODDR2_inst3 (
   .Q (clk25m[3]),   // 1-bit DDR output data
   .C0(clkout_div),   // 1-bit clock input
   .C1(~clkout_div),   // 1-bit clock input
   .CE(clk25m_on),//(1), // 1-bit clock enable input
   .D0(0), // 1-bit data input (associated with C0)
   .D1(1), // 1-bit data input (associated with C1)
   .R (0),   // 1-bit reset input
   .S (0)    // 1-bit set input
);

DCM_CLKGEN #( // {{{
	.CLKFXDV_DIVIDE(4), // CLKFXDV divide value (2, 4, 8, 16, 32)
	.CLKFX_DIVIDE(1), // Divide value - D - (1-256)
	.CLKFX_MD_MAX(0.0), // Specify maximum M/D ratio for timing anlysis
	.CLKFX_MULTIPLY(4), // Multiply value - M - (2-256)
	.CLKIN_PERIOD(40.0), // Input clock period specified in nS
	.SPREAD_SPECTRUM("NONE"), // Spread Spectrum mode "NONE", "CENTER_LOW_SPREAD", "CENTER_HIGH_SPREAD",
	// "VIDEO_LINK_M0", "VIDEO_LINK_M1" or "VIDEO_LINK_M2"
	.STARTUP_WAIT("FALSE") // Delay config DONE until DCM_CLKGEN LOCKED (TRUE/FALSE)
) DCM (
	.CLKFX(clkout), // 1-bit output: Generated clock output
	.CLKFX180(), // 1-bit output: Generated clock output 180 degree out of phase from CLKFX.
	.CLKFXDV(clkout_div), // 1-bit output: Divided clock output
	.LOCKED(locked), // 1-bit output: Locked output
	.PROGDONE(), // 1-bit output: Active high output to indicate the successful re-programming
	.STATUS(), // 2-bit output: DCM_CLKGEN status
	.CLKIN(clkin), // 1-bit input: Input clock
	.FREEZEDCM(1'b0), // 1-bit input: Prevents frequency adjustments to input clock
	.PROGCLK(1'b0), // 1-bit input: Clock input for M/D reconfiguration
	.PROGDATA(1'b0), // 1-bit input: Serial data input for M/D reconfiguration
	.PROGEN(1'b0), // 1-bit input: Active high program enable
	.RST(1'b0) // 1-bit input: Reset input pin
); // }}}

endmodule
module pmi_fifo #(
	parameter pmi_data_width = 8,
	parameter pmi_data_depth = 16,
	parameter pmi_full_flag = 16,
	parameter pmi_empty_flag = 0,
	parameter pmi_almost_full_flag = 1,
	parameter pmi_almost_empty_flag = 0,
	parameter pmi_regmode = "noreg",
	parameter pmi_family = 0,
	parameter module_type = "pmi_fifo",
	parameter pmi_implementation = "LUT"
)(
	input wire [pmi_data_width - 1 : 0] Data,
	input wire Clock,
	input wire WrEn,
	input wire RdEn,
	input wire Reset,
	output wire [pmi_data_width - 1 : 0] Q,
	output wire Empty,
	output wire Full,
	output wire AlmostEmpty,
	output wire AlmostFull
);   

fifo_uart fifo_uart_inst(
	.clk(Clock),
	.srst(Reset),
	.din(Data),
	.wr_en(WrEn),
	.rd_en(RdEn),
	.dout(Q),
	.full(Full),
	.almost_full(AlmostFull),
	.empty(Empty),
	.almost_empty(AlmostEmpty)
);

endmodule
module pmi_addsub #(
	parameter pmi_data_width    = 32,
	parameter pmi_result_width  = 32,
	parameter pmi_sign   = "off", // unused
	parameter pmi_family = 0,
	parameter module_type= "pmi_addsub"
	)(
	input wire [pmi_data_width - 1 : 0] DataA,
	input wire [pmi_data_width - 1 : 0] DataB,
	input wire Cin,
	input wire Add_Sub,
	output wire [pmi_result_width - 1 : 0]Result,
	output wire Cout,
	output wire Overflow
);

wire [pmi_data_width : 0] tmp_addResult = DataA + DataB + Cin;
wire [pmi_data_width : 0] tmp_subResult = DataA - DataB - !Cin;   

assign Result = (Add_Sub == 1) ? tmp_addResult[pmi_result_width - 1 : 0] : tmp_subResult[pmi_result_width - 1 : 0];
assign Cout = (Add_Sub == 1) ? tmp_addResult[pmi_data_width] : !tmp_subResult[pmi_data_width];
assign Overflow = Cout;

endmodule
module BB(
	input I,
	input T,
	output wire O,
	output wire B
);
assign  B = T ? 1'bz : I;
assign  O = B;
endmodule
module dbl_sha(
input         clk       ,
input         rst       ,

input         reg_dbl   ,
input         done      ,
input [255:0] hash      ,

output        dbl_vld   ,
output[31:0]  dbl_din    
);

/*
         _________________________
start __|                         |___
      ____ _                    __ ___
cnt   _0__|_1-------------------31|_0_

*/

reg start ;
reg [3:0] cnt ;//0~31
reg [255:0] hash_r ;

always @ ( posedge clk or posedge rst ) begin
	if( rst )
		start <= 1'b0 ;
	else if( reg_dbl )
		start <= 1'b1 ;
	else if( cnt == 15 )
		start <= 1'b0 ;
end

always @ ( posedge clk or posedge rst ) begin
	if( rst )
		cnt <= 'b0 ;
	else if( start )
		cnt <= cnt + 'b1 ;
end

always @ ( posedge clk ) begin
	if( done )
		hash_r <= hash ;
	else if( start && cnt != 7 )
		hash_r <= hash_r << 32 ;
	else if( start )//cnt == 15
		hash_r <= 256'h80000000_00000000_00000000_00000000_00000000_00000000_00000000_00000100 ;
end

assign dbl_vld = start ;
assign dbl_din = hash_r[255:255-31] ;

endmodule
module tx_timer(
input             clk          ,
input             rst          ,
input             reg_flush    ,
input  [31:0]     reg_tout     ,
input             timer_start  ,
output reg        timer_busy   ,
output [31:0]     timer_cnt       
);

reg [25:0] timer ;

assign timer_cnt = {6'b0,timer} ;

always @ ( posedge clk ) begin
	if( rst || (timer == reg_tout) || reg_flush )
		timer <= 'b0 ;
	else if( timer_start )
		timer <= 'b1 ;
	else if( |timer && (timer < reg_tout))
		timer <= 'b1 + timer ;
end

always @ ( posedge clk ) begin
	if( rst )
		timer_busy <= 1'b0 ;
	else if( timer_start )
		timer_busy <= 1'b1 ;
	else if ( (timer == reg_tout[25:0]) && |reg_tout[25:0] )
		timer_busy <= 1'b0 ;
end
endmodule
module shift(
input        clk      ,
input        rst      ,
input        vld      ,
input  [1:0] cmd      ,
input        cmd_oen  ,
input  [7:0] din      ,
output       done     ,

output       sft_shcp ,
output       sft_ds   ,
output       sft_stcp ,
output       sft_mr_n ,
output       sft_oe_n 
);

reg sft_mr_n ;
reg sft_oe_n ;
always @ ( posedge clk or posedge rst ) begin
	if( rst )
		sft_mr_n <= 1'b1 ;
	else if( vld && cmd == 2'b00 )
		sft_mr_n <= 1'b0 ;
	else
		sft_mr_n <= 1'b1 ;
end

always @ ( posedge clk or posedge rst ) begin
	if( rst )
		sft_oe_n <= 1'b1 ;
	else if( vld && cmd == 2'b11 )
		sft_oe_n <= cmd_oen ;
end

//--------------------------------------------------
// shcp counter
//--------------------------------------------------
reg [5:0] shcp_cnt ;
always @ ( posedge clk ) begin
	if( rst )
		shcp_cnt <= 0 ;
	else if( vld && cmd == 2'b01 )
		shcp_cnt <= 1 ;
	else if( |shcp_cnt )
		shcp_cnt <= shcp_cnt + 1 ;
end

assign sft_shcp = shcp_cnt[2] ;

reg [7:0] data ;
always @ ( posedge clk ) begin
	if( vld && cmd == 2'b01 )
		data <= din ;
	else if( &shcp_cnt[2:0] )
		data <= data >> 1 ;
end

assign sft_ds = (vld&&cmd==2'b01) ? din[0] : data[0] ;


//--------------------------------------------------
// sft_stcp
//--------------------------------------------------
reg [5:0] stcp_cnt ;
always @ ( posedge clk ) begin
	if( rst )
		stcp_cnt <= 0 ;
	else if( vld && cmd == 2'b10 )
		stcp_cnt <= 1 ;
	else if( |stcp_cnt )
		stcp_cnt <= stcp_cnt + 1 ;
end
assign sft_stcp = stcp_cnt[2] ;

//--------------------------------------------------
// done
//--------------------------------------------------
assign done = (stcp_cnt == 63) || (shcp_cnt == 63) ;

endmodule
module adc_clkgen_with_edgedetect(
   `ifdef USE_POWER_PINS
      inout VDD,	// User area 1.8V supply
      inout VSS,	// User area ground
   `endif
   input wire ena_in,             // enable signal from the digital clock core. 0 halts the self-clocked loop
   input wire start_conv_in,         // triggers a conversion once with edge-detection
   input wire ndecision_finish_in,   // comparator signalizes finished conversion
   output wire clk_dig_out,           // digital clock
   output wire clk_comp_out,          // comparator clock
   input wire enable_dlycontrol_in,  // 0 = max delays, 1 = configurable delays
   input wire [4:0] dlycontrol1_in,  // delay 1 of 3 in loop. Delay = 5ns*dlycontrol1
   input wire [4:0] dlycontrol2_in,  // delay 2 of 3 in loop. Delay = 5ns*dlycontrol2
   input wire [4:0] dlycontrol3_in,  // delay 3 of 3 in loop. Delay = 5ns*dlycontrol3
   input wire [5:0] dlycontrol4_in,  // edge detect pulse width. Delay = 5ns*dlycontrol4
   // additional buffers for sample matrix
   input wire sample_p_in,           
   input wire sample_n_in,
   output wire sample_p_out,
   output wire sample_n_out
   );
endmodule
module scboundary(
   `ifdef USE_POWER_PINS
      inout VDD,	// User area 1.8V supply
      inout VSS		// User area ground
   `endif
   );
endmodule
module adc_array_matrix_12bit (
   `ifdef USE_POWER_PINS
      inout VDD,	// User area 1.8V supply
      inout VSS,	// User area ground
   `endif
   input vcm,
   input sample,sample_n,
   input [15:0] row_n,
   input [15:0] rowon_n,
   input [15:0] rowoff_n,
   input [31:0] col_n,
   input [31:0] col,
   input [2:0] en_bit_n,
   input en_C0_n,
   input sw, sw_n, analog_in,
   output ctop);
endmodule
module adc_vcm_generator(
   `ifdef USE_POWER_PINS
      inout VDD,	// User area 1.8V supply
      inout VSS,	// User area ground
   `endif
   output vcm,
   input wire clk
   );
endmodule
module adc_comp_latch(
   `ifdef USE_POWER_PINS
      inout VDD,	// User area 1.8V supply
      inout VSS,	// User area ground
   `endif
   input wire clk,
   input wire inp,
   input wire inn,
   output wire comp_trig,
   output wire latch_qn,
   output wire latch_q
   );
endmodule