dakies/OSS_Verilog huggingface dataset:
module ac97_soc(clk, wclk, rst,
		ps_ce, resume, suspended,
		sync, out_le, in_valid, ld, valid
		);

input		clk, wclk, rst;
input		ps_ce;
input		resume;
output		suspended;
output		sync;
output	[5:0]	out_le;
output	[2:0]	in_valid;
output		ld;
output		valid;

////////////////////////////////////////////////////////////////////
//
// Local Wires
//

reg	[7:0]	cnt;
reg		sync_beat;
reg		sync_resume;
reg	[5:0]	out_le;
reg		ld;
reg		valid;
reg	[2:0]	in_valid;
reg		bit_clk_r;
reg		bit_clk_r1;
reg		bit_clk_e;
reg		suspended;
wire		to;
reg	[5:0]	to_cnt;
reg	[3:0]	res_cnt;
wire		resume_done;

assign sync = sync_beat | sync_resume;

////////////////////////////////////////////////////////////////////
//
// Misc Logic
//

always @(posedge clk or negedge rst)
	if(!rst)		cnt <= #1 8'hff;
	else
	if(suspended)		cnt <= #1 8'hff;
	else			cnt <= #1 cnt + 8'h1;

always @(posedge clk)
	ld <= #1 (cnt == 8'h00);

always @(posedge clk)
	sync_beat <= #1 (cnt == 8'h00) | ((cnt > 8'h00) & (cnt < 8'h10));

always @(posedge clk)
	valid <= #1 (cnt > 8'h39);

always @(posedge clk)
	out_le[0] <= #1 (cnt == 8'h11);		// Slot 0 Latch Enable

always @(posedge clk)
	out_le[1] <= #1 (cnt == 8'h25);		// Slot 1 Latch Enable

always @(posedge clk)
	out_le[2] <= #1 (cnt == 8'h39);		// Slot 2 Latch Enable

always @(posedge clk)
	out_le[3] <= #1 (cnt == 8'h4d);		// Slot 3 Latch Enable

always @(posedge clk)
	out_le[4] <= #1 (cnt == 8'h61);		// Slot 4 Latch Enable

always @(posedge clk)
	out_le[5] <= #1 (cnt == 8'h89);		// Slot 6 Latch Enable

always @(posedge clk)
	in_valid[0] <= #1 (cnt > 8'h4d);	// Input Slot 3 Valid

always @(posedge clk)
	in_valid[1] <= #1 (cnt > 8'h61);	// Input Slot 3 Valid

always @(posedge clk)
	in_valid[2] <= #1 (cnt > 8'h89);	// Input Slot 3 Valid

////////////////////////////////////////////////////////////////////
//
// Suspend Detect
//

always @(posedge wclk)
	bit_clk_r <= #1 clk;

always @(posedge wclk)
	bit_clk_r1 <= #1 bit_clk_r;

always @(posedge wclk)
	bit_clk_e <= #1 (bit_clk_r & !bit_clk_r1) | (!bit_clk_r & bit_clk_r1);

always @(posedge wclk)
	suspended <= #1 to;

assign to = (to_cnt == `AC97_SUSP_DET);

always @(posedge wclk or negedge rst)
	if(!rst)		to_cnt <= #1 6'h0;
	else
	if(bit_clk_e)		to_cnt <= #1 6'h0;
	else
	if(!to)			to_cnt <= #1 to_cnt + 6'h1;

////////////////////////////////////////////////////////////////////
//
// Resume Signaling
//

always @(posedge wclk or negedge rst)
	if(!rst)			sync_resume <= #1 1'b0;
	else
	if(resume_done)			sync_resume <= #1 1'b0;
	else
	if(suspended & resume)		sync_resume <= #1 1'b1;

assign resume_done = (res_cnt == `AC97_RES_SIG);

always @(posedge wclk)
	if(!sync_resume)	res_cnt <= #1 4'h0;
	else
	if(ps_ce)		res_cnt <= #1 res_cnt + 4'h1;

endmodule
module ac97_out_fifo(clk, rst, en, mode, din, we, dout, re, status, full, empty);

input		clk, rst;
input		en;
input	[1:0]	mode;
input	[31:0]	din;
input		we;
output	[19:0]	dout;
input		re;
output	[1:0]	status;
output		full;
output		empty;


////////////////////////////////////////////////////////////////////
//
// Local Wires
//

reg	[31:0]	mem[0:3];

reg	[2:0]	wp;
reg	[3:0]	rp;

wire	[2:0]	wp_p1;

reg	[1:0]	status;
reg	[19:0]	dout;
wire	[31:0]	dout_tmp;
wire	[15:0]	dout_tmp1;
wire		m16b;
reg		empty;

////////////////////////////////////////////////////////////////////
//
// Misc Logic
//

assign m16b = (mode == 2'h0);	// 16 Bit Mode

always @(posedge clk)
	if(!en)		wp <= #1 3'h0;
	else
	if(we)		wp <= #1 wp_p1;

assign wp_p1 = wp + 3'h1;

always @(posedge clk)
	if(!en)		rp <= #1 4'h0;
	else
	if(re & m16b)	rp <= #1 rp + 4'h1;
	else
	if(re & !m16b)	rp <= #1 rp + 4'h2;

always @(posedge clk)
	status <= #1 (wp[1:0] - rp[2:1]) - 2'h1;

wire	[3:0]	rp_p1 = rp[3:0] + 4'h1;

always @(posedge clk)
	empty <= #1 (rp_p1[3:1] == wp[2:0]) & (m16b ? rp_p1[0] : 1'b1);

assign full  = (wp[1:0] == rp[2:1]) & (wp[2] != rp[3]);

// Fifo Output
assign dout_tmp = mem[ rp[2:1] ];

// Fifo Output Half Word Select
assign dout_tmp1 = rp[0] ? dout_tmp[31:16] : dout_tmp[15:0];

always @(posedge clk)
	if(!en)		dout <= #1 20'h0;
	else
	if(re)
		case(mode)	// synopsys parallel_case full_case
		   2'h0: dout <= #1 {dout_tmp1, 4'h0};		// 16 Bit Output
		   2'h1: dout <= #1 {dout_tmp[17:0], 2'h0};	// 18 bit Output
		   2'h2: dout <= #1 dout_tmp[19:0];		// 20 Bit Output
		endcase

always @(posedge clk)
	if(we)	mem[wp[1:0]] <= #1 din;

endmodule
module ac97_out_fifo(clk, rst, en, mode, din, we, dout, re, status, full, empty);

input		clk, rst;
input		en;
input	[1:0]	mode;
input	[31:0]	din;
input		we;
output	[19:0]	dout;
input		re;
output	[1:0]	status;
output		full;
output		empty;


////////////////////////////////////////////////////////////////////
//
// Local Wires
//

reg	[31:0]	mem[0:7];

reg	[3:0]	wp;
reg	[4:0]	rp;

wire	[3:0]	wp_p1;

reg	[1:0]	status;
reg	[19:0]	dout;
wire	[31:0]	dout_tmp;
wire	[15:0]	dout_tmp1;
wire		m16b;
reg		empty;

////////////////////////////////////////////////////////////////////
//
// Misc Logic
//

assign m16b = (mode == 2'h0);	// 16 Bit Mode

always @(posedge clk)
	if(!en)		wp <= #1 4'h0;
	else
	if(we)		wp <= #1 wp_p1;

assign wp_p1 = wp + 4'h1;

always @(posedge clk)
	if(!en)		rp <= #1 5'h0;
	else
	if(re & m16b)	rp <= #1 rp + 5'h1;
	else
	if(re & !m16b)	rp <= #1 rp + 5'h2;

always @(posedge clk)
	status <= #1 (wp[2:1] - rp[3:2]) - 2'h1;

wire	[4:0]	rp_p1 = rp[4:0] + 5'h1;

always @(posedge clk)
	empty <= #1 (rp_p1[4:1] == wp[3:0]) & (m16b ? rp_p1[0] : 1'b1);

assign full  = (wp[2:0] == rp[3:1]) & (wp[3] != rp[4]);

// Fifo Output
assign dout_tmp = mem[ rp[3:1] ];

// Fifo Output Half Word Select
assign dout_tmp1 = rp[0] ? dout_tmp[31:16] : dout_tmp[15:0];

always @(posedge clk)
	if(!en)		dout <= #1 20'h0;
	else
	if(re)
		case(mode)	// synopsys parallel_case full_case
		   2'h0: dout <= #1 {dout_tmp1, 4'h0};		// 16 Bit Output
		   2'h1: dout <= #1 {dout_tmp[17:0], 2'h0};	// 18 bit Output
		   2'h2: dout <= #1 dout_tmp[19:0];		// 20 Bit Output
		endcase


always @(posedge clk)
	if(we)	mem[wp[2:0]] <= #1 din;

endmodule
module ac97_out_fifo(clk, rst, en, mode, din, we, dout, re, status, full, empty);

input		clk, rst;
input		en;
input	[1:0]	mode;
input	[31:0]	din;
input		we;
output	[19:0]	dout;
input		re;
output	[1:0]	status;
output		full;
output		empty;


////////////////////////////////////////////////////////////////////
//
// Local Wires
//

reg	[31:0]	mem[0:15];

reg	[4:0]	wp;
reg	[5:0]	rp;

wire	[4:0]	wp_p1;

reg	[1:0]	status;
reg	[19:0]	dout;
wire	[31:0]	dout_tmp;
wire	[15:0]	dout_tmp1;
wire		m16b;
reg		empty;

////////////////////////////////////////////////////////////////////
//
// Misc Logic
//

assign m16b = (mode == 2'h0);	// 16 Bit Mode

always @(posedge clk)
	if(!en)		wp <= #1 5'h0;
	else
	if(we)		wp <= #1 wp_p1;

assign wp_p1 = wp + 4'h1;

always @(posedge clk)
	if(!en)		rp <= #1 6'h0;
	else
	if(re & m16b)	rp <= #1 rp + 6'h1;
	else
	if(re & !m16b)	rp <= #1 rp + 6'h2;

always @(posedge clk)
	status <= #1 (wp[3:2] - rp[4:3]) - 2'h1;

wire	[5:0]	rp_p1 = rp[5:0] + 6'h1;

always @(posedge clk)
	empty <= #1 (rp_p1[5:1] == wp[4:0]) & (m16b ? rp_p1[0] : 1'b1);

assign full  = (wp[3:0] == rp[4:1]) & (wp[4] != rp[5]);

// Fifo Output
assign dout_tmp = mem[ rp[4:1] ];

// Fifo Output Half Word Select
assign dout_tmp1 = rp[0] ? dout_tmp[31:16] : dout_tmp[15:0];

always @(posedge clk)
	if(!en)		dout <= #1 20'h0;
	else
	if(re)
		case(mode)	// synopsys parallel_case full_case
		   2'h0: dout <= #1 {dout_tmp1, 4'h0};		// 16 Bit Output
		   2'h1: dout <= #1 {dout_tmp[17:0], 2'h0};	// 18 bit Output
		   2'h2: dout <= #1 dout_tmp[19:0];		// 20 Bit Output
		endcase


always @(posedge clk)
	if(we)	mem[wp[3:0]] <= #1 din;

endmodule
module ac97_int(clk, rst,

		// Register File Interface
		int_set,

		// FIFO Interface
		cfg, status, full_empty, full, empty, re, we
		);

input		clk, rst;
output	[2:0]	int_set;

input	[7:0]	cfg;
input	[1:0]	status;
input		full_empty, full, empty, re, we;

////////////////////////////////////////////////////////////////////
//
// Local Wires
//

reg	[2:0]	int_set;

////////////////////////////////////////////////////////////////////
//
// Interrupt Logic
//

always @(posedge clk or negedge rst)
	if(!rst)	int_set[0] <= #1 1'b0;
	else
	case(cfg[5:4])	// synopsys parallel_case full_case
			// 1/4 full/empty
	   2'h2: int_set[0] <= #1 cfg[0] & (full_empty | (status == 2'h0));
			// 1/2 full/empty
	   2'h1: int_set[0] <= #1 cfg[0] & (full_empty | (status[1] == 1'h0));
			// 3/4 full/empty
	   2'h0: int_set[0] <= #1 cfg[0] & (full_empty | (status < 2'h3));	
	   2'h3: int_set[0] <= #1 cfg[0] & full_empty;
	endcase

always @(posedge clk or negedge rst)
	if(!rst)	int_set[1] <= #1 1'b0;
	else
	if(empty & re)	int_set[1] <= #1 1'b1;

always @(posedge clk or negedge rst)
	if(!rst)	int_set[2] <= #1 1'b0;
	else
	if(full & we)	int_set[2] <= #1 1'b1;

endmodule
module ac97_wb_if(clk, rst,

		wb_data_i, wb_data_o, wb_addr_i, wb_sel_i, wb_we_i, wb_cyc_i,
		wb_stb_i, wb_ack_o, wb_err_o, 

		adr, dout, rf_din, i3_din, i4_din, i6_din,
		rf_we, rf_re, o3_we, o4_we, o6_we, o7_we, o8_we, o9_we,
		i3_re, i4_re, i6_re

		);

input		clk,rst;

// WISHBONE Interface
input	[31:0]	wb_data_i;
output	[31:0]	wb_data_o;
input	[31:0]	wb_addr_i;
input	[3:0]	wb_sel_i;
input		wb_we_i;
input		wb_cyc_i;
input		wb_stb_i;
output		wb_ack_o;
output		wb_err_o;

// Internal Interface
output	[3:0]	adr;
output	[31:0]	dout;
input	[31:0]	rf_din, i3_din, i4_din, i6_din;
output		rf_we;
output		rf_re;
output		o3_we, o4_we, o6_we, o7_we, o8_we, o9_we;
output		i3_re, i4_re, i6_re;

////////////////////////////////////////////////////////////////////
//
// Local Wires
//

reg	[31:0]	wb_data_o;
reg	[31:0]	dout;
reg		wb_ack_o;

reg		rf_we;
reg		o3_we, o4_we, o6_we, o7_we, o8_we, o9_we;
reg		i3_re, i4_re, i6_re;

reg		we1, we2;
wire		we;
reg		re2, re1;
wire		re;

////////////////////////////////////////////////////////////////////
//
// Modules
//

assign adr = wb_addr_i[5:2];

assign wb_err_o = 1'b0;

always @(posedge clk)
	dout <= #1 wb_data_i;

always @(posedge clk)
	case(wb_addr_i[6:2])	// synopsys parallel_case full_case
	   5'he: wb_data_o <= #1 i3_din;
	   5'hf: wb_data_o <= #1 i4_din;
	   5'h10: wb_data_o <= #1 i6_din;
	   default: wb_data_o <= #1 rf_din;
	endcase

always @(posedge clk)
	re1 <= #1 !re2 & wb_cyc_i & wb_stb_i & !wb_we_i & `AC97_REG_SEL;

always @(posedge clk)
	re2 <= #1 re & wb_cyc_i & wb_stb_i & !wb_we_i ;

assign re = re1 & !re2 & wb_cyc_i & wb_stb_i & !wb_we_i;

assign rf_re = re & (wb_addr_i[6:2] < 5'h8);

always @(posedge clk)
	we1 <= #1 !we & wb_cyc_i & wb_stb_i & wb_we_i & `AC97_REG_SEL;

always @(posedge clk)
	we2 <= #1 we1 & wb_cyc_i & wb_stb_i & wb_we_i;

assign we = we1 & !we2 & wb_cyc_i & wb_stb_i & wb_we_i;

always @(posedge clk)
	wb_ack_o <= #1 (re | we) & wb_cyc_i & wb_stb_i & ~wb_ack_o;

always @(posedge clk)
	rf_we <= #1 we & (wb_addr_i[6:2] < 5'h8);

always @(posedge clk)
	o3_we <= #1 we & (wb_addr_i[6:2] == 5'h8);

always @(posedge clk)
	o4_we <= #1 we & (wb_addr_i[6:2] == 5'h9);

always @(posedge clk)
	o6_we <= #1 we & (wb_addr_i[6:2] == 5'ha);

always @(posedge clk)
	o7_we <= #1 we & (wb_addr_i[6:2] == 5'hb);

always @(posedge clk)
	o8_we <= #1 we & (wb_addr_i[6:2] == 5'hc);

always @(posedge clk)
	o9_we <= #1 we & (wb_addr_i[6:2] == 5'hd);

always @(posedge clk)
	i3_re <= #1 re & (wb_addr_i[6:2] == 5'he);

always @(posedge clk)
	i4_re <= #1 re & (wb_addr_i[6:2] == 5'hf);

always @(posedge clk)
	i6_re <= #1 re & (wb_addr_i[6:2] == 5'h10);

endmodule
module ac97_in_fifo(clk, rst, en, mode, din, we, dout, re, status, full, empty);

input		clk, rst;
input		en;
input	[1:0]	mode;
input	[19:0]	din;
input		we;
output	[31:0]	dout;
input		re;
output	[1:0]	status;
output		full;
output		empty;


////////////////////////////////////////////////////////////////////
//
// Local Wires
//

reg	[31:0]	mem[0:3];
reg	[31:0]	dout;

reg	[3:0]	wp;
reg	[2:0]	rp;

wire	[3:0]	wp_p1;

reg	[1:0]	status;
reg	[15:0]	din_tmp1;
reg	[31:0]	din_tmp;
wire		m16b;
reg		full, empty;

////////////////////////////////////////////////////////////////////
//
// Misc Logic
//

assign m16b = (mode == 2'h0);	// 16 Bit Mode

always @(posedge clk)
	if(!en)		wp <= #1 4'h0;
	else
	if(we)		wp <= #1 wp_p1;

assign wp_p1 = m16b ? (wp + 4'h1) : (wp + 4'h2);

always @(posedge clk)
	if(!en)		rp <= #1 3'h0;
	else
	if(re)		rp <= #1 rp + 3'h1;

always @(posedge clk)
	status <= #1 ((rp[1:0] - wp[2:1]) - 2'h1);

always @(posedge clk)
	empty <= #1 (wp[3:1] == rp[2:0]) & (m16b ? !wp[0] : 1'b0);

always @(posedge clk)
	full  <= #1 (wp[2:1] == rp[1:0]) & (wp[3] != rp[2]);

// Fifo Output
always @(posedge clk)
	dout <= #1 mem[ rp[1:0] ];

// Fifo Input Half Word Latch
always @(posedge clk)
	if(we & !wp[0])	din_tmp1 <= #1 din[19:4];

always @(mode or din_tmp1 or din)
	case(mode)	// synopsys parallel_case full_case
	   2'h0: din_tmp = {din[19:4], din_tmp1};	// 16 Bit Output
	   2'h1: din_tmp = {14'h0, din[19:2]};		// 18 bit Output
	   2'h2: din_tmp = {11'h0, din[19:0]};		// 20 Bit Output
	endcase

always @(posedge clk)
	if(we & (!m16b | (m16b & wp[0]) ) )	mem[ wp[2:1] ] <= #1 din_tmp;

endmodule
module ac97_in_fifo(clk, rst, en, mode, din, we, dout, re, status, full, empty);

input		clk, rst;
input		en;
input	[1:0]	mode;
input	[19:0]	din;
input		we;
output	[31:0]	dout;
input		re;
output	[1:0]	status;
output		full;
output		empty;


////////////////////////////////////////////////////////////////////
//
// Local Wires
//

reg	[31:0]	mem[0:7];
reg	[31:0]	dout;

reg	[4:0]	wp;
reg	[3:0]	rp;

wire	[4:0]	wp_p1;

reg	[1:0]	status;
reg	[15:0]	din_tmp1;
reg	[31:0]	din_tmp;
wire		m16b;
reg		full, empty;

////////////////////////////////////////////////////////////////////
//
// Misc Logic
//

assign m16b = (mode == 2'h0);	// 16 Bit Mode

always @(posedge clk)
	if(!en)		wp <= #1 5'h0;
	else
	if(we)		wp <= #1 wp_p1;

assign wp_p1 = m16b ? (wp + 5'h1) : (wp + 5'h2);

always @(posedge clk)
	if(!en)		rp <= #1 4'h0;
	else
	if(re)		rp <= #1 rp + 4'h1;

always @(posedge clk)
	status <= #1 ((rp[2:1] - wp[3:2]) - 2'h1);

always @(posedge clk)
	empty <= #1 (wp[4:1] == rp[3:0]) & (m16b ? !wp[0] : 1'b0);

always @(posedge clk)
	full  <= #1 (wp[3:1] == rp[2:0]) & (wp[4] != rp[3]);

// Fifo Output
always @(posedge clk)
	dout <= #1 mem[ rp[2:0] ];

// Fifo Input Half Word Latch
always @(posedge clk)
	if(we & !wp[0])	din_tmp1 <= #1 din[19:4];

always @(mode or din_tmp1 or din)
	case(mode)	// synopsys parallel_case full_case
	   2'h0: din_tmp = {din[19:4], din_tmp1};	// 16 Bit Output
	   2'h1: din_tmp = {14'h0, din[19:2]};		// 18 bit Output
	   2'h2: din_tmp = {11'h0, din[19:0]};		// 20 Bit Output
	endcase

always @(posedge clk)
	if(we & (!m16b | (m16b & wp[0]) ) )	mem[ wp[3:1] ] <= #1 din_tmp;

endmodule
module ac97_in_fifo(clk, rst, en, mode, din, we, dout, re, status, full, empty);

input		clk, rst;
input		en;
input	[1:0]	mode;
input	[19:0]	din;
input		we;
output	[31:0]	dout;
input		re;
output	[1:0]	status;
output		full;
output		empty;


////////////////////////////////////////////////////////////////////
//
// Local Wires
//

reg	[31:0]	mem[0:15];
reg	[31:0]	dout;

reg	[5:0]	wp;
reg	[4:0]	rp;

wire	[5:0]	wp_p1;

reg	[1:0]	status;
reg	[15:0]	din_tmp1;
reg	[31:0]	din_tmp;
wire		m16b;
reg		full, empty;

////////////////////////////////////////////////////////////////////
//
// Misc Logic
//

assign m16b = (mode == 2'h0);	// 16 Bit Mode

always @(posedge clk)
	if(!en)		wp <= #1 6'h0;
	else
	if(we)		wp <= #1 wp_p1;

assign wp_p1 = m16b ? (wp + 6'h1) : (wp + 6'h2);

always @(posedge clk)
	if(!en)		rp <= #1 5'h0;
	else
	if(re)		rp <= #1 rp + 5'h1;

always @(posedge clk)
	status <= #1 ((rp[3:2] - wp[4:3]) - 2'h1);

always @(posedge clk)
	empty <= #1 (wp[5:1] == rp[4:0]) & (m16b ? !wp[0] : 1'b0);

always @(posedge clk)
	full  <= #1 (wp[4:1] == rp[3:0]) & (wp[5] != rp[4]);

// Fifo Output
always @(posedge clk)
	dout <= #1 mem[ rp[3:0] ];

// Fifo Input Half Word Latch
always @(posedge clk)
	if(we & !wp[0])	din_tmp1 <= #1 din[19:4];

always @(mode or din_tmp1 or din)
	case(mode)	// synopsys parallel_case full_case
	   2'h0: din_tmp = {din[19:4], din_tmp1};	// 16 Bit Output
	   2'h1: din_tmp = {14'h0, din[19:2]};		// 18 bit Output
	   2'h2: din_tmp = {11'h0, din[19:0]};		// 20 Bit Output
	endcase

always @(posedge clk)
	if(we & (!m16b | (m16b & wp[0]) ) )	mem[ wp[4:1] ] <= #1 din_tmp;

endmodule
module ac97_fifo_ctrl(	clk, 
			valid, ch_en, srs, full_empty, req, crdy,
			en_out, en_out_l
			);
input		clk;
input		valid;
input		ch_en;		// Channel Enable
input		srs;		// Sample Rate Select
input		full_empty;	// Fifo Status
input		req;		// Codec Request
input		crdy;		// Codec Ready
output		en_out;		// Output read/write pulse
output		en_out_l;	// Latched Output

////////////////////////////////////////////////////////////////////
//
// Local Wires
//

reg	en_out_l, en_out_l2;
reg	full_empty_r;

////////////////////////////////////////////////////////////////////
//
// Misc Logic
//

always @(posedge clk)
	if(!valid)	full_empty_r <= #1 full_empty;

always @(posedge clk)
	if(valid & ch_en & !full_empty_r & crdy & (!srs | (srs & req) ) )
		en_out_l <= #1 1'b1;
	else
	if(!valid & !(ch_en & !full_empty_r & crdy & (!srs | (srs & req) )) )
		en_out_l <= #1 1'b0;

always @(posedge clk)
	en_out_l2 <= #1 en_out_l & valid;

assign en_out = en_out_l & !en_out_l2 & valid;

endmodule
module sasc_brg(clk, rst, div0, div1, sio_ce, sio_ce_x4);
input		clk;
input		rst;
input	[7:0]	div0, div1;
output		sio_ce, sio_ce_x4;

///////////////////////////////////////////////////////////////////
//
// Local Wires and Registers
//

reg	[7:0]	ps;
reg		ps_clr;
reg	[7:0]	br_cnt;
reg		br_clr;
reg		sio_ce_x4_r;
reg	[1:0]	cnt;
reg		sio_ce, sio_ce_x4;
reg		sio_ce_r ;
reg		sio_ce_x4_t;

///////////////////////////////////////////////////////////////////
//
// Boud Rate Generator
//

// -----------------------------------------------------
// Prescaler
always @(posedge clk)
	if(!rst)	ps <= #1 8'h0;
	else
	if(ps_clr)	ps <= #1 8'h0;
	else		ps <= #1 ps + 8'h1;

always @(posedge clk)
	ps_clr <= #1 (ps == div0);	// Desired number of cycles less 2

// -----------------------------------------------------
// Oversampled Boud Rate (x4)
always @(posedge clk)
	if(!rst)	br_cnt <= #1 8'h0;
	else
	if(br_clr)	br_cnt <= #1 8'h0;
	else
	if(ps_clr)	br_cnt <= #1 br_cnt + 8'h1;

always @(posedge clk)
	br_clr <= #1 (br_cnt == div1); // Prciese number of PS cycles

always @(posedge clk)
	sio_ce_x4_r <= #1 br_clr;

always @(posedge clk)
	sio_ce_x4_t <= #1 !sio_ce_x4_r & br_clr;

always @(posedge clk)
	sio_ce_x4 <= #1 sio_ce_x4_t;

// -----------------------------------------------------
// Actual Boud rate
always @(posedge clk)
	if(!rst)			cnt <= #1 2'h0;
	else
	if(!sio_ce_x4_r & br_clr)	cnt <= #1 cnt + 2'h1;

always @(posedge clk)
	sio_ce_r <= #1 (cnt == 2'h0);

always @(posedge clk)
	sio_ce <= #1 !sio_ce_r & (cnt == 2'h0);

endmodule
module sasc_fifo4(clk, rst, clr,  din, we, dout, re, full, empty);

input		clk, rst;
input		clr;
input   [7:0]	din;
input		we;
output  [7:0]	dout;
input		re;
output		full, empty;


////////////////////////////////////////////////////////////////////
//
// Local Wires
//

reg     [7:0]	mem[0:3];
reg     [1:0]   wp;
reg     [1:0]   rp;
wire    [1:0]   wp_p1;
wire    [1:0]   wp_p2;
wire    [1:0]   rp_p1;
wire		full, empty;
reg		gb;

////////////////////////////////////////////////////////////////////
//
// Misc Logic
//

always @(posedge clk or negedge rst)
        if(!rst)	wp <= #1 2'h0;
        else
        if(clr)		wp <= #1 2'h0;
        else
        if(we)		wp <= #1 wp_p1;

assign wp_p1 = wp + 2'h1;
assign wp_p2 = wp + 2'h2;

always @(posedge clk or negedge rst)
        if(!rst)	rp <= #1 2'h0;
        else
        if(clr)		rp <= #1 2'h0;
        else
        if(re)		rp <= #1 rp_p1;

assign rp_p1 = rp + 2'h1;

// Fifo Output
assign  dout = mem[ rp ];

// Fifo Input 
always @(posedge clk)
        if(we)     mem[ wp ] <= #1 din;

// Status
assign empty = (wp == rp) & !gb;
assign full  = (wp == rp) &  gb;

// Guard Bit ...
always @(posedge clk)
	if(!rst)			gb <= #1 1'b0;
	else
	if(clr)				gb <= #1 1'b0;
	else
	if((wp_p1 == rp) & we)		gb <= #1 1'b1;
	else
	if(re)				gb <= #1 1'b0;

endmodule
module  crp(P, R, K_sub);
output	[1:32]	P;
input	[1:32]	R;
input	[1:48]	K_sub;

wire	[1:48] E;
wire	[1:48] X;
wire	[1:32] S;

assign E[1:48] = {	R[32], R[1], R[2], R[3], R[4], R[5], R[4], R[5],
			R[6], R[7], R[8], R[9], R[8], R[9], R[10], R[11],
			R[12], R[13], R[12], R[13], R[14], R[15], R[16],
			R[17], R[16], R[17], R[18], R[19], R[20], R[21],
			R[20], R[21], R[22], R[23], R[24], R[25], R[24],
			R[25], R[26], R[27], R[28], R[29], R[28], R[29],
			R[30], R[31], R[32], R[1]};

assign X = E ^ K_sub;

sbox1 u0( .addr(X[01:06]), .dout(S[01:04]) );
sbox2 u1( .addr(X[07:12]), .dout(S[05:08]) );
sbox3 u2( .addr(X[13:18]), .dout(S[09:12]) );
sbox4 u3( .addr(X[19:24]), .dout(S[13:16]) );
sbox5 u4( .addr(X[25:30]), .dout(S[17:20]) );
sbox6 u5( .addr(X[31:36]), .dout(S[21:24]) );
sbox7 u6( .addr(X[37:42]), .dout(S[25:28]) );
sbox8 u7( .addr(X[43:48]), .dout(S[29:32]) );

assign P[1:32] = {	S[16], S[7], S[20], S[21], S[29], S[12], S[28],
			S[17], S[1], S[15], S[23], S[26], S[5], S[18],
			S[31], S[10], S[2], S[8], S[24], S[14], S[32],
			S[27], S[3], S[9], S[19], S[13], S[30], S[6],
			S[22], S[11], S[4], S[25]};

endmodule
module  sbox5(addr, dout);
input	[1:6] addr;
output	[1:4] dout;
reg	[1:4] dout;

always @(addr) begin
    case ({addr[1], addr[6], addr[2:5]})	//synopsys full_case parallel_case
         0:  dout =  2;
         1:  dout = 12;
         2:  dout =  4;
         3:  dout =  1;
         4:  dout =  7;
         5:  dout = 10;
         6:  dout = 11;
         7:  dout =  6;
         8:  dout =  8;
         9:  dout =  5;
        10:  dout =  3;
        11:  dout = 15;
        12:  dout = 13;
        13:  dout =  0;
        14:  dout = 14;
        15:  dout =  9;

        16:  dout = 14;
        17:  dout = 11;
        18:  dout =  2;
        19:  dout = 12;
        20:  dout =  4;
        21:  dout =  7;
        22:  dout = 13;
        23:  dout =  1;
        24:  dout =  5;
        25:  dout =  0;
        26:  dout = 15;
        27:  dout = 10;
        28:  dout =  3;
        29:  dout =  9;
        30:  dout =  8;
        31:  dout =  6;

        32:  dout =  4;
        33:  dout =  2;
        34:  dout =  1;
        35:  dout = 11;
        36:  dout = 10;
        37:  dout = 13;
        38:  dout =  7;
        39:  dout =  8;
        40:  dout = 15;
        41:  dout =  9;
        42:  dout = 12;
        43:  dout =  5;
        44:  dout =  6;
        45:  dout =  3;
        46:  dout =  0;
        47:  dout = 14;

        48:  dout = 11;
        49:  dout =  8;
        50:  dout = 12;
        51:  dout =  7;
        52:  dout =  1;
        53:  dout = 14;
        54:  dout =  2;
        55:  dout = 13;
        56:  dout =  6;
        57:  dout = 15;
        58:  dout =  0;
        59:  dout =  9;
        60:  dout = 10;
        61:  dout =  4;
        62:  dout =  5;
        63:  dout =  3;

    endcase
    end

endmodule
module  sbox4(addr, dout);
input	[1:6] addr;
output	[1:4] dout;
reg	[1:4] dout;

always @(addr) begin
    case ({addr[1], addr[6], addr[2:5]})	//synopsys full_case parallel_case
         0:  dout =  7;
         1:  dout = 13;
         2:  dout = 14;
         3:  dout =  3;
         4:  dout =  0;
         5:  dout =  6;
         6:  dout =  9;
         7:  dout = 10;
         8:  dout =  1;
         9:  dout =  2;
        10:  dout =  8;
        11:  dout =  5;
        12:  dout = 11;
        13:  dout = 12;
        14:  dout =  4;
        15:  dout = 15;

        16:  dout = 13;
        17:  dout =  8;
        18:  dout = 11;
        19:  dout =  5;
        20:  dout =  6;
        21:  dout = 15;
        22:  dout =  0;
        23:  dout =  3;
        24:  dout =  4;
        25:  dout =  7;
        26:  dout =  2;
        27:  dout = 12;
        28:  dout =  1;
        29:  dout = 10;
        30:  dout = 14;
        31:  dout =  9;

        32:  dout = 10;
        33:  dout =  6;
        34:  dout =  9;
        35:  dout =  0;
        36:  dout = 12;
        37:  dout = 11;
        38:  dout =  7;
        39:  dout = 13;
        40:  dout = 15;
        41:  dout =  1;
        42:  dout =  3;
        43:  dout = 14;
        44:  dout =  5;
        45:  dout =  2;
        46:  dout =  8;
        47:  dout =  4;

        48:  dout =  3;
        49:  dout = 15;
        50:  dout =  0;
        51:  dout =  6;
        52:  dout = 10;
        53:  dout =  1;
        54:  dout = 13;
        55:  dout =  8;
        56:  dout =  9;
        57:  dout =  4;
        58:  dout =  5;
        59:  dout = 11;
        60:  dout = 12;
        61:  dout =  7;
        62:  dout =  2;
        63:  dout = 14;

    endcase
    end

endmodule
module des(desOut, desIn, key, decrypt, roundSel, clk);
output	[63:0]	desOut;
input	[63:0]	desIn;
input	[55:0]	key;
input		decrypt;
input	[3:0]	roundSel;
input		clk;

wire	[1:48]	K_sub;
wire	[1:64]	IP, FP;
reg	[1:32]	L, R;
wire	[1:32]	Xin;
wire	[1:32]	Lout, Rout;
wire	[1:32]	out;

assign Lout = (roundSel == 0) ? IP[33:64] : R;
assign Xin  = (roundSel == 0) ? IP[01:32] : L;
assign Rout = Xin ^ out;
assign FP = { Rout, Lout};

crp u0( .P(out), .R(Lout), .K_sub(K_sub) );

always @(posedge clk)
        L <= #1 Lout;

always @(posedge clk)
        R <= #1 Rout;
        
// Select a subkey from key.
key_sel u1(
	.K_sub(		K_sub		),
	.K(		key		),
	.roundSel(	roundSel	),
	.decrypt(	decrypt		)
	);

// Perform initial permutation
assign IP[1:64] = {	desIn[06], desIn[14], desIn[22], desIn[30], desIn[38], desIn[46],
			desIn[54], desIn[62], desIn[04], desIn[12], desIn[20], desIn[28],
			desIn[36], desIn[44], desIn[52], desIn[60], desIn[02], desIn[10], 
			desIn[18], desIn[26], desIn[34], desIn[42], desIn[50], desIn[58], 
			desIn[00], desIn[08], desIn[16], desIn[24], desIn[32], desIn[40], 
			desIn[48], desIn[56], desIn[07], desIn[15], desIn[23], desIn[31], 
			desIn[39], desIn[47], desIn[55], desIn[63], desIn[05], desIn[13],
			desIn[21], desIn[29], desIn[37], desIn[45], desIn[53], desIn[61],
			desIn[03], desIn[11], desIn[19], desIn[27], desIn[35], desIn[43],
			desIn[51], desIn[59], desIn[01], desIn[09], desIn[17], desIn[25],
			desIn[33], desIn[41], desIn[49], desIn[57] };

// Perform final permutation
assign desOut = {	FP[40], FP[08], FP[48], FP[16], FP[56], FP[24], FP[64], FP[32], 
			FP[39], FP[07], FP[47], FP[15], FP[55], FP[23], FP[63], FP[31], 
			FP[38], FP[06], FP[46], FP[14], FP[54], FP[22], FP[62], FP[30], 
			FP[37], FP[05], FP[45], FP[13], FP[53], FP[21], FP[61], FP[29], 
			FP[36], FP[04], FP[44], FP[12], FP[52], FP[20], FP[60], FP[28], 
			FP[35], FP[03], FP[43], FP[11], FP[51], FP[19], FP[59], FP[27],
			FP[34], FP[02], FP[42], FP[10], FP[50], FP[18], FP[58], FP[26], 
			FP[33], FP[01], FP[41], FP[09], FP[49], FP[17], FP[57], FP[25] };


endmodule
module  sbox8(addr, dout);
input	[1:6] addr;
output	[1:4] dout;
reg	[1:4] dout;

always @(addr) begin
    case ({addr[1], addr[6], addr[2:5]})	//synopsys full_case parallel_case
         0:  dout = 13;
         1:  dout =  2;
         2:  dout =  8;
         3:  dout =  4;
         4:  dout =  6;
         5:  dout = 15;
         6:  dout = 11;
         7:  dout =  1;
         8:  dout = 10;
         9:  dout =  9;
        10:  dout =  3;
        11:  dout = 14;
        12:  dout =  5;
        13:  dout =  0;
        14:  dout = 12;
        15:  dout =  7;

        16:  dout =  1;
        17:  dout = 15;
        18:  dout = 13;
        19:  dout =  8;
        20:  dout = 10;
        21:  dout =  3;
        22:  dout =  7;
        23:  dout =  4;
        24:  dout = 12;
        25:  dout =  5;
        26:  dout =  6;
        27:  dout = 11;
        28:  dout =  0;
        29:  dout = 14;
        30:  dout =  9;
        31:  dout =  2;

        32:  dout =  7;
        33:  dout = 11;
        34:  dout =  4;
        35:  dout =  1;
        36:  dout =  9;
        37:  dout = 12;
        38:  dout = 14;
        39:  dout =  2;
        40:  dout =  0;
        41:  dout =  6;
        42:  dout = 10;
        43:  dout = 13;
        44:  dout = 15;
        45:  dout =  3;
        46:  dout =  5;
        47:  dout =  8;

        48:  dout =  2;
        49:  dout =  1;
        50:  dout = 14;
        51:  dout =  7;
        52:  dout =  4;
        53:  dout = 10;
        54:  dout =  8;
        55:  dout = 13;
        56:  dout = 15;
        57:  dout = 12;
        58:  dout =  9;
        59:  dout =  0;
        60:  dout =  3;
        61:  dout =  5;
        62:  dout =  6;
        63:  dout = 11;

    endcase
    end

endmodule
module  sbox1(addr, dout);
input	[1:6] addr;
output	[1:4] dout;
reg	[1:4] dout;

always @(addr) begin
    case ({addr[1], addr[6], addr[2:5]})	//synopsys full_case parallel_case
         0:  dout =  14;
         1:  dout =   4;
         2:  dout =  13;
         3:  dout =   1;
         4:  dout =   2;
         5:  dout =  15;
         6:  dout =  11;
         7:  dout =   8;
         8:  dout =   3;
         9:  dout =  10;
        10:  dout =   6;
        11:  dout =  12;
        12:  dout =   5;
        13:  dout =   9;
        14:  dout =   0;
        15:  dout =   7;

        16:  dout =   0;
        17:  dout =  15;
        18:  dout =   7;
        19:  dout =   4;
        20:  dout =  14;
        21:  dout =   2;
        22:  dout =  13;
        23:  dout =   1;
        24:  dout =  10;
        25:  dout =   6;
        26:  dout =  12;
        27:  dout =  11;
        28:  dout =   9;
        29:  dout =   5;
        30:  dout =   3;
        31:  dout =   8;

        32:  dout =   4;
        33:  dout =   1;
        34:  dout =  14;
        35:  dout =   8;
        36:  dout =  13;
        37:  dout =   6;
        38:  dout =   2;
        39:  dout =  11;
        40:  dout =  15;
        41:  dout =  12;
        42:  dout =   9;
        43:  dout =   7;
        44:  dout =   3;
        45:  dout =  10;
        46:  dout =   5;
        47:  dout =   0;

        48:  dout =  15;
        49:  dout =  12;
        50:  dout =   8;
        51:  dout =   2;
        52:  dout =   4;
        53:  dout =   9;
        54:  dout =   1;
        55:  dout =   7;
        56:  dout =   5;
        57:  dout =  11;
        58:  dout =   3;
        59:  dout =  14;
        60:  dout =  10;
        61:  dout =   0;
        62:  dout =   6;
        63:  dout =  13;

    endcase
    end

endmodule
module  sbox7(addr, dout);
input	[1:6] addr;
output	[1:4] dout;
reg	[1:4] dout;

always @(addr) begin
    case ({addr[1], addr[6], addr[2:5]})	//synopsys full_case parallel_case
         0:  dout =  4;
         1:  dout = 11;
         2:  dout =  2;
         3:  dout = 14;
         4:  dout = 15;
         5:  dout =  0;
         6:  dout =  8;
         7:  dout = 13;
         8:  dout =  3;
         9:  dout = 12;
        10:  dout =  9;
        11:  dout =  7;
        12:  dout =  5;
        13:  dout = 10;
        14:  dout =  6;
        15:  dout =  1;

        16:  dout = 13;
        17:  dout =  0;
        18:  dout = 11;
        19:  dout =  7;
        20:  dout =  4;
        21:  dout =  9;
        22:  dout =  1;
        23:  dout = 10;
        24:  dout = 14;
        25:  dout =  3;
        26:  dout =  5;
        27:  dout = 12;
        28:  dout =  2;
        29:  dout = 15;
        30:  dout =  8;
        31:  dout =  6;

        32:  dout =  1;
        33:  dout =  4;
        34:  dout = 11;
        35:  dout = 13;
        36:  dout = 12;
        37:  dout =  3;
        38:  dout =  7;
        39:  dout = 14;
        40:  dout = 10;
        41:  dout = 15;
        42:  dout =  6;
        43:  dout =  8;
        44:  dout =  0;
        45:  dout =  5;
        46:  dout =  9;
        47:  dout =  2;

        48:  dout =  6;
        49:  dout = 11;
        50:  dout = 13;
        51:  dout =  8;
        52:  dout =  1;
        53:  dout =  4;
        54:  dout = 10;
        55:  dout =  7;
        56:  dout =  9;
        57:  dout =  5;
        58:  dout =  0;
        59:  dout = 15;
        60:  dout = 14;
        61:  dout =  2;
        62:  dout =  3;
        63:  dout = 12;

    endcase
    end

endmodule
module  sbox3(addr, dout);
input	[1:6] addr;
output	[1:4] dout;
reg	[1:4] dout;

always @(addr) begin
    case ({addr[1], addr[6], addr[2:5]})	//synopsys full_case parallel_case
         0:  dout = 10;
         1:  dout =  0;
         2:  dout =  9;
         3:  dout = 14;
         4:  dout =  6;
         5:  dout =  3;
         6:  dout = 15;
         7:  dout =  5;
         8:  dout =  1;
         9:  dout = 13;
        10:  dout = 12;
        11:  dout =  7;
        12:  dout = 11;
        13:  dout =  4;
        14:  dout =  2;
        15:  dout =  8;

        16:  dout = 13;
        17:  dout =  7;
        18:  dout =  0;
        19:  dout =  9;
        20:  dout =  3;
        21:  dout =  4;
        22:  dout =  6;
        23:  dout = 10;
        24:  dout =  2;
        25:  dout =  8;
        26:  dout =  5;
        27:  dout = 14;
        28:  dout = 12;
        29:  dout = 11;
        30:  dout = 15;
        31:  dout =  1;

        32:  dout = 13;
        33:  dout =  6;
        34:  dout =  4;
        35:  dout =  9;
        36:  dout =  8;
        37:  dout = 15;
        38:  dout =  3;
        39:  dout =  0;
        40:  dout = 11;
        41:  dout =  1;
        42:  dout =  2;
        43:  dout = 12;
        44:  dout =  5;
        45:  dout = 10;
        46:  dout = 14;
        47:  dout =  7;

        48:  dout =  1;
        49:  dout = 10;
        50:  dout = 13;
        51:  dout =  0;
        52:  dout =  6;
        53:  dout =  9;
        54:  dout =  8;
        55:  dout =  7;
        56:  dout =  4;
        57:  dout = 15;
        58:  dout = 14;
        59:  dout =  3;
        60:  dout = 11;
        61:  dout =  5;
        62:  dout =  2;
        63:  dout = 12;

    endcase
    end

endmodule
module  sbox2(addr, dout);
input	[1:6] addr;
output	[1:4] dout;
reg	[1:4] dout;

always @(addr) begin
    case ({addr[1], addr[6], addr[2:5]})	//synopsys full_case parallel_case
         0:  dout = 15;
         1:  dout =  1;
         2:  dout =  8;
         3:  dout = 14;
         4:  dout =  6;
         5:  dout = 11;
         6:  dout =  3;
         7:  dout =  4;
         8:  dout =  9;
         9:  dout =  7;
        10:  dout =  2;
        11:  dout = 13;
        12:  dout = 12;
        13:  dout =  0;
        14:  dout =  5;
        15:  dout = 10;

        16:  dout =  3;
        17:  dout = 13;
        18:  dout =  4;
        19:  dout =  7;
        20:  dout = 15;
        21:  dout =  2;
        22:  dout =  8;
        23:  dout = 14;
        24:  dout = 12;
        25:  dout =  0;
        26:  dout =  1;
        27:  dout = 10;
        28:  dout =  6;
        29:  dout =  9;
        30:  dout = 11;
        31:  dout =  5;

        32:  dout =  0;
        33:  dout = 14;
        34:  dout =  7;
        35:  dout = 11;
        36:  dout = 10;
        37:  dout =  4;
        38:  dout = 13;
        39:  dout =  1;
        40:  dout =  5;
        41:  dout =  8;
        42:  dout = 12;
        43:  dout =  6;
        44:  dout =  9;
        45:  dout =  3;
        46:  dout =  2;
        47:  dout = 15;

        48:  dout = 13;
        49:  dout =  8;
        50:  dout = 10;
        51:  dout =  1;
        52:  dout =  3;
        53:  dout = 15;
        54:  dout =  4;
        55:  dout =  2;
        56:  dout = 11;
        57:  dout =  6;
        58:  dout =  7;
        59:  dout = 12;
        60:  dout =  0;
        61:  dout =  5;
        62:  dout = 14;
        63:  dout =  9;

    endcase
    end

endmodule
module  sbox6(addr, dout);
input	[1:6] addr;
output	[1:4] dout;
reg	[1:4] dout;

always @(addr) begin
    case ({addr[1], addr[6], addr[2:5]})	//synopsys full_case parallel_case
         0:  dout = 12;
         1:  dout =  1;
         2:  dout = 10;
         3:  dout = 15;
         4:  dout =  9;
         5:  dout =  2;
         6:  dout =  6;
         7:  dout =  8;
         8:  dout =  0;
         9:  dout = 13;
        10:  dout =  3;
        11:  dout =  4;
        12:  dout = 14;
        13:  dout =  7;
        14:  dout =  5;
        15:  dout = 11;

        16:  dout = 10;
        17:  dout = 15;
        18:  dout =  4;
        19:  dout =  2;
        20:  dout =  7;
        21:  dout = 12;
        22:  dout =  9;
        23:  dout =  5;
        24:  dout =  6;
        25:  dout =  1;
        26:  dout = 13;
        27:  dout = 14;
        28:  dout =  0;
        29:  dout = 11;
        30:  dout =  3;
        31:  dout =  8;

        32:  dout =  9;
        33:  dout = 14;
        34:  dout = 15;
        35:  dout =  5;
        36:  dout =  2;
        37:  dout =  8;
        38:  dout = 12;
        39:  dout =  3;
        40:  dout =  7;
        41:  dout =  0;
        42:  dout =  4;
        43:  dout = 10;
        44:  dout =  1;
        45:  dout = 13;
        46:  dout = 11;
        47:  dout =  6;

        48:  dout =  4;
        49:  dout =  3;
        50:  dout =  2;
        51:  dout = 12;
        52:  dout =  9;
        53:  dout =  5;
        54:  dout = 15;
        55:  dout = 10;
        56:  dout = 11;
        57:  dout = 14;
        58:  dout =  1;
        59:  dout =  7;
        60:  dout =  6;
        61:  dout =  0;
        62:  dout =  8;
        63:  dout = 13;

    endcase
    end

endmodule
module pcm_slv_top(	clk, rst,
	
			ssel,

			// PCM
			pcm_clk_i, pcm_sync_i, pcm_din_i, pcm_dout_o,

			// Internal Interface
			din_i, dout_o, re_i, we_i);

input		clk, rst;
input	[2:0]	ssel;	// Number of bits to delay (0-7)
input		pcm_clk_i, pcm_sync_i, pcm_din_i;
output		pcm_dout_o;
input	[7:0]	din_i;
output	[7:0]	dout_o;
input		re_i;
input	[1:0]	we_i;

///////////////////////////////////////////////////////////////////
//
// Local Wires and Registers
//

reg		pclk_t, pclk_s, pclk_r;
wire		pclk_ris, pclk_fal;
reg		psync;
reg		pcm_sync_r1, pcm_sync_r2, pcm_sync_r3;
reg		tx_go;
wire		tx_data_le;
reg	[15:0]	tx_hold_reg;
reg	[7:0]	tx_hold_byte_h, tx_hold_byte_l;
reg	[3:0]	tx_cnt;
wire		tx_done;
reg	[15:0]	rx_hold_reg, rx_reg;
wire		rx_data_le;
reg		rxd_t, rxd;
reg		tx_go_r1, tx_go_r2;
reg	[7:0]	psa;

///////////////////////////////////////////////////////////////////
//
// Misc Logic
//

always @(posedge clk)
	pclk_t <= #1 pcm_clk_i;

always @(posedge clk)
	pclk_s <= #1 pclk_t;

always @(posedge clk)
	pclk_r <= #1 pclk_s;

assign pclk_ris = !pclk_r &  pclk_s;
assign pclk_fal =  pclk_r & !pclk_s;

///////////////////////////////////////////////////////////////////
//
// Retrieve Sync Signal
//

always @(posedge clk)	// Latch it at falling edge
	if(pclk_fal)	pcm_sync_r1 <= #1 pcm_sync_i;

always @(posedge clk)	// resync to rising edge
	if(pclk_ris)	psa <= #1 {psa[6:0], pcm_sync_r1};

always @(posedge clk)	//delay bit N
	pcm_sync_r2 <= #1 psa[ssel];

always @(posedge clk)	// edge detector
	pcm_sync_r3 <= #1 pcm_sync_r2;

always @(posedge clk)
	psync <= #1 !pcm_sync_r3 & pcm_sync_r2;

///////////////////////////////////////////////////////////////////
//
// Transmit Logic
//

assign tx_data_le = tx_go & pclk_ris;

always @(posedge clk)
	if(we_i[1])	tx_hold_byte_h <= #1 din_i;

always @(posedge clk)
	if(we_i[0])	tx_hold_byte_l <= #1 din_i;

always @(posedge clk)
	if(!rst)	tx_go <= #1 1'b0;
	else
	if(psync)	tx_go <= #1 1'b1;
	else
	if(tx_done)	tx_go <= #1 1'b0;

always @(posedge clk)
	if(!rst)	tx_hold_reg <= #1 16'h0;
	else
	if(psync)	tx_hold_reg <= #1 {tx_hold_byte_h, tx_hold_byte_l};
	else
	if(tx_data_le)	tx_hold_reg <= #1 {tx_hold_reg[14:0],1'b0};

assign	pcm_dout_o = tx_hold_reg[15];
	
always @(posedge clk)
	if(!rst)	tx_cnt <= #1 4'h0;
	else
	if(tx_data_le)	tx_cnt <= tx_cnt + 4'h1;

assign tx_done = (tx_cnt == 4'hf) & tx_data_le;

///////////////////////////////////////////////////////////////////
//
// Recieve Logic
//

always @(posedge clk)
	if(pclk_ris)	tx_go_r1 <= #1 tx_go;

always @(posedge clk)
	if(pclk_ris)	tx_go_r2 <= #1 tx_go_r1;

// Receive is in sync with transmit ...
always @(posedge clk)
	if(pclk_fal)	rxd_t <= #1 pcm_din_i;

always @(posedge clk)
	rxd <= #1 rxd_t;

assign rx_data_le = (tx_go_r1 | tx_go) & pclk_fal;

always @(posedge clk)
	if(!rst)	rx_hold_reg <= #1 16'h0;
	else
	if(rx_data_le)	rx_hold_reg <= #1 {rx_hold_reg[14:0], rxd};

always @(posedge clk)
	if(!rst)				rx_reg <= #1 16'h0;
	else
	if(tx_go_r1 & !tx_go & pclk_ris)	rx_reg <= #1 rx_hold_reg;

assign dout_o = re_i ? rx_reg[15:8] : rx_reg[7:0];

endmodule
module pci_io_mux_ad_load_crit
(
    load_in,
    load_on_transfer_in,
    pci_irdy_in,
    pci_trdy_in,
    load_out
);

input  load_in,
       load_on_transfer_in,
       pci_irdy_in,
       pci_trdy_in ;

output load_out ;

assign load_out = load_in || (load_on_transfer_in && ~pci_irdy_in && ~pci_trdy_in) ;

endmodule
module pci_perr_en_crit
(
    reset_in,
    clk_in,
    perr_en_out,
    perr_en_reg_out,
    non_critical_par_in,
    pci_par_in,
    perr_generate_in,
    par_err_response_in
) ;
output  perr_en_out,
        perr_en_reg_out ;

input   reset_in,
        clk_in,
        non_critical_par_in,
        pci_par_in,
        perr_generate_in,
        par_err_response_in ;

wire perr = par_err_response_in && perr_generate_in && ( non_critical_par_in ^ pci_par_in ) ;

// PERR# is enabled for two clocks after parity error is detected - one cycle active, another inactive
reg perr_en_reg_out ;
always@(posedge reset_in or posedge clk_in)
begin
    if ( reset_in )
        perr_en_reg_out <= #1 1'b0 ;
    else
        perr_en_reg_out <= #1 perr ;
end

assign perr_en_out = perr || perr_en_reg_out ;

endmodule
module pci_conf_cyc_addr_dec
(
    ccyc_addr_in,
    ccyc_addr_out
) ;

input   [31:0]  ccyc_addr_in ;
output  [31:0]  ccyc_addr_out ;
reg     [31:11]  ccyc_addr_31_11 ;

// lower 11 address lines are alweys going through unchanged
assign ccyc_addr_out = {ccyc_addr_31_11, ccyc_addr_in[10:0]} ;

// configuration cycle type indicator
wire ccyc_type = ccyc_addr_in[0] ;

always@(ccyc_addr_in or ccyc_type)
begin
    if (ccyc_type)
        // type 1 cycle - address goes through unchanged
        ccyc_addr_31_11 = ccyc_addr_in[31:11] ;
    else
    begin
        // type 0 conf. cycle - decode device number field to appropriate value
        case (ccyc_addr_in[15:11])
            5'h00:ccyc_addr_31_11 = 21'h00_0001 ;
            5'h01:ccyc_addr_31_11 = 21'h00_0002 ;
            5'h02:ccyc_addr_31_11 = 21'h00_0004 ;
            5'h03:ccyc_addr_31_11 = 21'h00_0008 ;
            5'h04:ccyc_addr_31_11 = 21'h00_0010 ;
            5'h05:ccyc_addr_31_11 = 21'h00_0020 ;
            5'h06:ccyc_addr_31_11 = 21'h00_0040 ;
            5'h07:ccyc_addr_31_11 = 21'h00_0080 ;
            5'h08:ccyc_addr_31_11 = 21'h00_0100 ;
            5'h09:ccyc_addr_31_11 = 21'h00_0200 ;
            5'h0A:ccyc_addr_31_11 = 21'h00_0400 ;
            5'h0B:ccyc_addr_31_11 = 21'h00_0800 ;
            5'h0C:ccyc_addr_31_11 = 21'h00_1000 ;
            5'h0D:ccyc_addr_31_11 = 21'h00_2000 ;
            5'h0E:ccyc_addr_31_11 = 21'h00_4000 ;
            5'h0F:ccyc_addr_31_11 = 21'h00_8000 ;
            5'h10:ccyc_addr_31_11 = 21'h01_0000 ;
            5'h11:ccyc_addr_31_11 = 21'h02_0000 ;
            5'h12:ccyc_addr_31_11 = 21'h04_0000 ;
            5'h13:ccyc_addr_31_11 = 21'h08_0000 ;
            5'h14:ccyc_addr_31_11 = 21'h10_0000 ;
            default: ccyc_addr_31_11 = 21'h00_0000 ;
        endcase
    end
end

endmodule
module pci_frame_crit
(
    pci_frame_out,
    force_frame_in,
    slow_frame_in,
    pci_stop_in
) ;

output  pci_frame_out ;
input   force_frame_in,
        slow_frame_in,
        pci_stop_in ;

assign  pci_frame_out   = force_frame_in && (slow_frame_in || ~pci_stop_in) ;

endmodule
module pci_mas_ad_load_crit
(
    ad_load_out,
    ad_load_in,
    ad_load_on_grant_in,
    pci_gnt_in
);
output ad_load_out ;
input  ad_load_in,
       ad_load_on_grant_in,
       pci_gnt_in ;

assign ad_load_out = ad_load_in || ( ad_load_on_grant_in && !pci_gnt_in ) ;
endmodule
module pci_rst_int
(
	clk_in,
	// reset signals
	rst_i,
	pci_rstn_in,
	conf_soft_res_in,
	reset,
	pci_rstn_out,
	pci_rstn_en_out,
	rst_o,
	// interrupt signals
	pci_intan_in,
	conf_int_in,
	int_i,
	pci_intan_out,
	pci_intan_en_out,
	int_o,
	conf_isr_int_prop_out,
    init_complete_in
);

input	clk_in;
// RESET inputs and outputs
input	rst_i;
input	pci_rstn_in;
input	conf_soft_res_in;
output	reset;
output	pci_rstn_out;
output	pci_rstn_en_out;
output	rst_o;

// INTERRUPT inputs and outputs
input	pci_intan_in;
input	conf_int_in;
input	int_i;
output	pci_intan_out;
output	pci_intan_en_out;
output	int_o;
output	conf_isr_int_prop_out;

input   init_complete_in ;

/*--------------------------------------------------------------------------------------------------------
RESET logic
--------------------------------------------------------------------------------------------------------*/
assign pci_rstn_out			= 1'b0 ;
// host implementation of the bridge gets its reset from WISHBONE bus - RST_I and propagates it to PCI bus
`ifdef HOST
  assign reset				= rst_i ;
  `ifdef ACTIVE_LOW_OE
  assign pci_rstn_en_out	= ~(rst_i || conf_soft_res_in) ;
  `else
  assign pci_rstn_en_out        = rst_i || conf_soft_res_in ;
  `endif
  assign rst_o				= 1'b0 ;
`else
// guest implementation of the bridge gets its reset from PCI bus - RST# and propagates it to WISHBONE bus
`ifdef GUEST
  assign reset 				= ~pci_rstn_in ;
  assign rst_o 				= (~pci_rstn_in) || conf_soft_res_in ;
  `ifdef ACTIVE_LOW_OE
  assign pci_rstn_en_out	        = 1'b1 ; // disabled
  `else
  assign pci_rstn_en_out                = 1'b0 ; // disabled
  `endif
`endif
`endif

/*--------------------------------------------------------------------------------------------------------
INTERRUPT logic
--------------------------------------------------------------------------------------------------------*/
assign pci_intan_out = 1'b0 ;
// host implementation of the bridge gets its interrupt from PCI bus - INTA# and propagates it to WISHBONE bus
`ifdef HOST
  assign conf_isr_int_prop_out  = ~pci_intan_in ;
  assign int_o                  = conf_int_in ;
  `ifdef ACTIVE_LOW_OE
  assign pci_intan_en_out       = 1'b1 ; // disabled
  `else
  assign pci_intan_en_out       = 1'b0 ; // disabled
  `endif
`else
// guest implementation of the bridge gets its interrupt from WISHBONE bus - INT_I and propagates it to PCI bus
`ifdef GUEST
    wire interrupt_a_en;
    pci_out_reg inta
    (
        .reset_in     ( reset ),
        .clk_in       ( clk_in) ,
        .dat_en_in    ( 1'b1 ),
        .en_en_in     ( init_complete_in ),
        .dat_in       ( 1'b0 ) , // active low
        .en_in        ( conf_int_in ) ,
        .en_out       ( interrupt_a_en ),
        .dat_out      ( )
    );
  assign conf_isr_int_prop_out = int_i ;
  assign int_o                 = 1'b0 ;
  assign pci_intan_en_out      = interrupt_a_en ;
`endif
`endif


endmodule
module pci_io_mux_ad_en_crit
(
    ad_en_in,
    pci_frame_in,
    pci_trdy_in,
    pci_stop_in,
    ad_en_out
);
input  ad_en_in,
       pci_frame_in,
       pci_trdy_in,
       pci_stop_in ;
output ad_en_out ;

assign ad_en_out = ad_en_in && ( ~pci_frame_in || (pci_trdy_in && pci_stop_in) ) ;
endmodule