dakies/OSS_Verilog huggingface dataset:
module mem_ext(
  input W0_clk,
  input [9:0] W0_addr,
  input W0_en,
  input [31:0] W0_data,
  input [3:0] W0_mask,
  input R0_clk,
  input [9:0] R0_addr,
  input R0_en,
  output [31:0] R0_data
);

  // WARNING: This should be a true dual port RAM (1read and 1write), however
  //          bsg_fakeram doesn't support this yet. Using a simple 1 rw as a
  //          place holder.
  // WARNING: Ignoring R0_clk (assuming it is the same as W0_clk)
  wire [9:0] addr;
  wire en;
  assign addr_int = W0_en ? W0_addr : R0_addr;
  assign en = W0_en | R0_en;


  fakeram45_1024x32 mem (
    .clk      (W0_clk   ),
    .rd_out   (R0_data  ),
    .ce_in    (en    ),
    .we_in    (W0_en     ),
    .w_mask_in({  {8{W0_mask[3]}}
                 ,{8{W0_mask[2]}}
                 ,{8{W0_mask[1]}}
                 ,{8{W0_mask[0]}}}
      ),
    .addr_in  (addr_int  ),
    .wd_in    (W0_data  )
  );


endmodule
module hard_mem_1rw_bit_mask_d64_w96_wrapper(clk_i, reset_i, data_i,
     addr_i, v_i, w_mask_i, w_i, data_o);
  input clk_i, reset_i, v_i, w_i;
  input [95:0] data_i, w_mask_i;
  input [5:0] addr_i;
  output [95:0] data_o;
  wire clk_i, reset_i, v_i, w_i;
  wire [95:0] data_i, w_mask_i;
  wire [5:0] addr_i;
  wire [95:0] data_o;

  fakeram45_64x96 mem (
    .clk      (clk_i   ),
    .rd_out   (data_o  ),
    .ce_in    (1'b1    ),
    .we_in    (w_i     ),
    .w_mask_in(w_mask_i),
    .addr_in  (addr_i  ),
    .wd_in    (data_i  )
  );

endmodule
module hard_mem_1rw_byte_mask_d512_w64_wrapper(clk_i, reset_i, data_i,
     addr_i, v_i, write_mask_i, w_i, data_o);
  input clk_i, reset_i, v_i, w_i;
  input [63:0] data_i;
  input [8:0] addr_i;
  input [7:0] write_mask_i;
  output [63:0] data_o;
  wire clk_i, reset_i, v_i, w_i;
  wire [63:0] data_i;
  wire [8:0] addr_i;
  wire [7:0] write_mask_i;
  wire [63:0] data_o;
  wire [63:0] wen;

  fakeram45_512x64 mem (
    .clk      (clk_i   ),
    .rd_out   (data_o  ),
    .ce_in    (1'b1    ),
    .we_in    (w_i     ),
    .w_mask_in({{8{write_mask_i[7]}},
                {8{write_mask_i[6]}},
                {8{write_mask_i[5]}},
                {8{write_mask_i[4]}},
                {8{write_mask_i[3]}},
                {8{write_mask_i[2]}},
                {8{write_mask_i[1]}},
                {8{write_mask_i[0]}}}
      ),
    .addr_in  (addr_i  ),
    .wd_in    (data_i  )
  );

endmodule
module hard_mem_1rw_bit_mask_d64_w15_wrapper(clk_i, reset_i, data_i,
     addr_i, v_i, w_mask_i, w_i, data_o);
  input clk_i, reset_i, v_i, w_i;
  input [14:0] data_i, w_mask_i;
  input [5:0] addr_i;
  output [14:0] data_o;
  wire clk_i, reset_i, v_i, w_i;
  wire [14:0] data_i, w_mask_i;
  wire [5:0] addr_i;
  wire [14:0] data_o;

  fakeram45_64x15 mem (
    .clk      (clk_i   ),
    .rd_out   (data_o  ),
    .ce_in    (1'b1    ),
    .we_in    (w_i     ),
    .w_mask_in(w_mask_i),
    .addr_in  (addr_i  ),
    .wd_in    (data_i  )
  );

endmodule
module aes_key_expand_128(clk, kld, key, wo_0, wo_1, wo_2, wo_3);
input		clk;
input		kld;
input	[127:0]	key;
output	[31:0]	wo_0, wo_1, wo_2, wo_3;
reg	[31:0]	w[3:0];
wire	[31:0]	tmp_w;
wire	[31:0]	subword;
wire	[31:0]	rcon;

assign wo_0 = w[0];
assign wo_1 = w[1];
assign wo_2 = w[2];
assign wo_3 = w[3];
always @(posedge clk)	w[0] <= #1 kld ? key[127:096] : w[0]^subword^rcon;
always @(posedge clk)	w[1] <= #1 kld ? key[095:064] : w[0]^w[1]^subword^rcon;
always @(posedge clk)	w[2] <= #1 kld ? key[063:032] : w[0]^w[2]^w[1]^subword^rcon;
always @(posedge clk)	w[3] <= #1 kld ? key[031:000] : w[0]^w[3]^w[2]^w[1]^subword^rcon;
assign tmp_w = w[3];
aes_sbox u0(	.a(tmp_w[23:16]), .d(subword[31:24]));
aes_sbox u1(	.a(tmp_w[15:08]), .d(subword[23:16]));
aes_sbox u2(	.a(tmp_w[07:00]), .d(subword[15:08]));
aes_sbox u3(	.a(tmp_w[31:24]), .d(subword[07:00]));
aes_rcon r0(	.clk(clk), .kld(kld), .out(rcon));
endmodule
module plusarg_reader #(parameter FORMAT="borked=%d", DEFAULT=0, WIDTH=1) (
   output [WIDTH-1:0] out
);

`ifdef SYNTHESIS
assign out = DEFAULT;
`else
reg [WIDTH-1:0] myplus;
assign out = myplus;

initial begin
   if (!$value$plusargs(FORMAT, myplus)) myplus = DEFAULT;
end
`endif

endmodule
module AsyncResetReg (d, q, en, clk, rst);
parameter RESET_VALUE = 0;

input  wire d;
output reg  q;
input  wire en;
input  wire clk;
input  wire rst;

   // There is a lot of initialization
   // here you don't normally find in Verilog
   // async registers because of scenarios in which reset
   // is not actually asserted cleanly at time 0,
   // and we want to make sure to properly model
   // that, yet Chisel codebase is absolutely intolerant
   // of Xs.
`ifndef SYNTHESIS
  initial begin:B0
    `ifdef RANDOMIZE
    integer    initvar;
    reg [31:0] _RAND;
    _RAND = {1{$random}};
    q = _RAND[0];
    `endif // RANDOMIZE
    if (rst) begin
      q = RESET_VALUE[0];
    end 
  end
`endif

   always @(posedge clk or posedge rst) begin

      if (rst) begin
         q <= RESET_VALUE[0];
      end else if (en) begin
         q <= d;
      end
   end
 
endmodule // AsyncResetReg
module ClockDivider3 (output reg clk_out, input clk_in);

   reg delay;

   initial begin
     clk_out = 1'b0;
     delay = 1'b0;
   end

   always @(posedge clk_in) begin
      if (clk_out == 1'b0) begin
        clk_out = 1'b1;
        delay <= 1'b0;
      end else if (delay == 1'b1) begin
        clk_out = 1'b0;
        delay <= 1'b0;
      end else begin
        delay <= 1'b1;
      end
   end

endmodule // ClockDivider3
module ClockDivider2 (output reg clk_out, input clk_in);

   initial clk_out = 1'b0;
   always @(posedge clk_in) begin
      clk_out = ~clk_out; // Must use =, NOT <=
   end

endmodule // ClockDivider2
module mc_refresh(clk, rst, 
		cs_need_rfr, ref_int, rfr_req, rfr_ack,
		rfr_ps_val
		);

input		clk, rst;
input	[7:0]	cs_need_rfr;
input	[2:0]	ref_int;
output		rfr_req;
input		rfr_ack;
input	[7:0]	rfr_ps_val;

////////////////////////////////////////////////////////////////////
//
// Local Registers & Wires
//

reg		rfr_en;
reg	[7:0]	ps_cnt;
wire		ps_cnt_clr;
reg		rfr_ce;
reg	[7:0]	rfr_cnt;
reg		rfr_clr;
reg		rfr_req;
reg		rfr_early;

/*
Refresh generation

The prescaler generates a 0.48828 uS clock enable

The refresh counter generates the following refresh rates:
(Actual values are about 0.63% below the desired values).
This is for a 200 Mhz WISHBONE Bus.
0.970 uS,
1.940
3.880
7.760
15.520
32.040
62.080
124.160 uS

(desired values)
0.976 uS
1.953
3.906
7.812
15.625
31.250
62.500
125.000 uS
*/

////////////////////////////////////////////////////////////////////
//
// Prescaler
//

always @(posedge clk or posedge rst)
	if(rst)		rfr_en <= #1 1'b0;
	else		rfr_en <= #1 |cs_need_rfr;

always @(posedge clk or posedge rst)
	if(rst)				ps_cnt <= #1 8'h0;
	else	
	if(ps_cnt_clr)			ps_cnt <= #1 8'h0;
	else	
	if(rfr_en)			ps_cnt <= #1 ps_cnt + 8'h1;

assign ps_cnt_clr = (ps_cnt == rfr_ps_val) & (rfr_ps_val != 8'h0);

always @(posedge clk or posedge rst)
	if(rst)		rfr_early <= #1 1'b0;
	else		rfr_early <= #1 (ps_cnt == rfr_ps_val);

////////////////////////////////////////////////////////////////////
//
// Refresh Counter
//

always @(posedge clk or posedge rst)
	if(rst)		rfr_ce <= #1 1'b0;
	else		rfr_ce <= #1 ps_cnt_clr;

always @(posedge clk or posedge rst)
	if(rst)			rfr_cnt <= #1 8'h0;
	else
	if(rfr_ack)		rfr_cnt <= #1 8'h0;
	else
	if(rfr_ce)		rfr_cnt <= #1 rfr_cnt + 8'h1;

always @(posedge clk)
	case(ref_int)		// synopsys full_case parallel_case
	   3'h0: rfr_clr <= #1  rfr_cnt[0]   & rfr_early;
	   3'h1: rfr_clr <= #1 &rfr_cnt[1:0] & rfr_early;
	   3'h2: rfr_clr <= #1 &rfr_cnt[2:0] & rfr_early;
	   3'h3: rfr_clr <= #1 &rfr_cnt[3:0] & rfr_early;
	   3'h4: rfr_clr <= #1 &rfr_cnt[4:0] & rfr_early;
	   3'h5: rfr_clr <= #1 &rfr_cnt[5:0] & rfr_early;
	   3'h6: rfr_clr <= #1 &rfr_cnt[6:0] & rfr_early;
	   3'h7: rfr_clr <= #1 &rfr_cnt[7:0] & rfr_early;
	endcase

always @(posedge clk or posedge rst)
	if(rst)			rfr_req <= #1 1'b0;
	else
	if(rfr_ack)		rfr_req <= #1 1'b0;
	else
	if(rfr_clr)		rfr_req <= #1 1'b1;

endmodule
module mc_rd_fifo(clk, rst, clr, din, we, dout, re);

input		clk, rst, clr;
input	[35:0]	din;
input		we;
output	[35:0]	dout;
input		re;

reg	[3:0]	rd_adr, wr_adr;
reg	[35:0]	r0, r1, r2, r3;
reg	[35:0]	dout;

always @(posedge clk or posedge rst)
	if(rst)		rd_adr <= #1 4'h1;
	else
	if(clr)		rd_adr <= #1 4'h1;
	else
	if(re)		rd_adr <= #1 {rd_adr[2:0], rd_adr[3]};

always @(posedge clk or posedge rst)
	if(rst)		wr_adr <= #1 4'h1;
	else
	if(clr)		wr_adr <= #1 4'h1;
	else
	if(we)		wr_adr <= #1 {wr_adr[2:0], wr_adr[3]};

always @(posedge clk)
	if(we & wr_adr[0])	r0 <= #1 din;

always @(posedge clk)
	if(we & wr_adr[1])	r1 <= #1 din;

always @(posedge clk)
	if(we & wr_adr[2])	r2 <= #1 din;

always @(posedge clk)
	if(we & wr_adr[3])	r3 <= #1 din;

always @(rd_adr or r0 or r1 or r2 or r3 or re or we or din)
	case(rd_adr)		// synopsys full_case parallel_case
	   4'h1:	dout = r0;
	   4'h2:	dout = r1;
	   4'h4:	dout = r2;
	   4'h8:	dout = r3;
	endcase

endmodule
module mc_incn_r(clk, inc_in, inc_out);

parameter	incN_width = 32;

input		clk;
input	[incN_width-1:0]	inc_in;
output	[incN_width-1:0]	inc_out;

parameter	incN_center = incN_width / 2;

reg	[incN_center:0]		out_r;
wire	[31:0]			tmp_zeros = 32'h0;
wire	[incN_center-1:0]	inc_next;

always @(posedge clk)
	out_r <= #1 inc_in[incN_center - 1:0] + {tmp_zeros[incN_center-2:0], 1'h1};

assign inc_out[incN_width-1:incN_center] = inc_in[incN_width-1:incN_center] + inc_next;

assign inc_next = out_r[incN_center] ?
			{tmp_zeros[incN_center-2:0], 1'h1} : tmp_zeros[incN_center-2:0];

assign inc_out[incN_center-1:0]  = out_r;

endmodule
module mc_obct(clk, rst, row_adr, bank_adr, bank_set, bank_clr, bank_clr_all,
		bank_open, any_bank_open, row_same);
input		clk, rst;
input	[12:0]	row_adr;
input	[1:0]	bank_adr;
input		bank_set;
input		bank_clr;
input		bank_clr_all;
output		bank_open;
output		any_bank_open;
output		row_same;

////////////////////////////////////////////////////////////////////
//
// Local Registers & Wires
//

reg		bank0_open, bank1_open, bank2_open, bank3_open;
reg		bank_open;
reg	[12:0]	b0_last_row;
reg	[12:0]	b1_last_row;
reg	[12:0]	b2_last_row;
reg	[12:0]	b3_last_row;
wire		row0_same, row1_same, row2_same, row3_same;
reg		row_same;

////////////////////////////////////////////////////////////////////
//
// Bank Open/Closed Tracking
//

always @(posedge clk or posedge rst)
	if(rst)					bank0_open <= #1 1'b0;
	else
	if((bank_adr == 2'h0) & bank_set)	bank0_open <= #1 1'b1;
	else
	if((bank_adr == 2'h0) & bank_clr)	bank0_open <= #1 1'b0;
	else
	if(bank_clr_all)			bank0_open <= #1 1'b0;

always @(posedge clk or posedge rst)
	if(rst)					bank1_open <= #1 1'b0;
	else
	if((bank_adr == 2'h1) & bank_set)	bank1_open <= #1 1'b1;
	else
	if((bank_adr == 2'h1) & bank_clr)	bank1_open <= #1 1'b0;
	else
	if(bank_clr_all)			bank1_open <= #1 1'b0;

always @(posedge clk or posedge rst)
	if(rst)					bank2_open <= #1 1'b0;
	else
	if((bank_adr == 2'h2) & bank_set)	bank2_open <= #1 1'b1;
	else
	if((bank_adr == 2'h2) & bank_clr)	bank2_open <= #1 1'b0;
	else
	if(bank_clr_all)			bank2_open <= #1 1'b0;

always @(posedge clk or posedge rst)
	if(rst)					bank3_open <= #1 1'b0;
	else
	if((bank_adr == 2'h3) & bank_set)	bank3_open <= #1 1'b1;
	else
	if((bank_adr == 2'h3) & bank_clr)	bank3_open <= #1 1'b0;
	else
	if(bank_clr_all)			bank3_open <= #1 1'b0;

always @(bank_adr or bank0_open or bank1_open or bank2_open or bank3_open)
	case(bank_adr)		// synopsys full_case parallel_case
	   2'h0: bank_open = bank0_open;
	   2'h1: bank_open = bank1_open;
	   2'h2: bank_open = bank2_open;
	   2'h3: bank_open = bank3_open;
	endcase

assign any_bank_open = bank0_open | bank1_open | bank2_open | bank3_open;

////////////////////////////////////////////////////////////////////
//
// Raw Address Tracking
//

always @(posedge clk)
	if((bank_adr == 2'h0) & bank_set)	b0_last_row <= #1 row_adr;

always @(posedge clk)
	if((bank_adr == 2'h1) & bank_set)	b1_last_row <= #1 row_adr;

always @(posedge clk)
	if((bank_adr == 2'h2) & bank_set)	b2_last_row <= #1 row_adr;

always @(posedge clk)
	if((bank_adr == 2'h3) & bank_set)	b3_last_row <= #1 row_adr;

////////////////////////////////////////////////////////////////////
//
// Raw address checking
//

assign row0_same = (b0_last_row == row_adr);
assign row1_same = (b1_last_row == row_adr);
assign row2_same = (b2_last_row == row_adr);
assign row3_same = (b3_last_row == row_adr);

always @(bank_adr or row0_same or row1_same or row2_same or row3_same)
	case(bank_adr)		// synopsys full_case parallel_case
	   2'h0: row_same = row0_same;
	   2'h1: row_same = row1_same;
	   2'h2: row_same = row2_same;
	   2'h3: row_same = row3_same;
	endcase

endmodule
module mc_obct_dummy(clk, rst, row_adr, bank_adr, bank_set, bank_clr, bank_clr_all,
		bank_open, any_bank_open, row_same);
input		clk, rst;
input	[12:0]	row_adr;
input	[1:0]	bank_adr;
input		bank_set;
input		bank_clr;
input		bank_clr_all;
output		bank_open;
output		any_bank_open;
output		row_same;

assign bank_open = 1'b0;
assign any_bank_open = 1'b0;
assign row_same = 1'b0;

endmodule
module mc_cs_rf(clk, rst, wb_we_i, din, rf_we, addr, csc, tms, poc, csc_mask, cs,
		wp_err, lmr_req, lmr_ack, init_req, init_ack );

input		clk, rst;
input		wb_we_i;
input	[31:0]	din;
input		rf_we;
input	[31:0]	addr;

output	[31:0]	csc;
output	[31:0]	tms;
input	[31:0]	poc;
input	[31:0]	csc_mask;
output		cs;
output		wp_err;

output		lmr_req;
input		lmr_ack;
output		init_req;
input		init_ack;

parameter	[2:0]	this_cs = 0;
parameter	[3:0]	reg_select = this_cs + 2;

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

reg	[31:0]	csc;
reg	[31:0]	tms;
wire		sel;
wire		cs_d;
wire		wp;
reg		inited;
reg		init_req;
reg		init_req_we;
reg		lmr_req;
reg		lmr_req_we;

////////////////////////////////////////////////////////////////////
//
// A kludge for cases where there is no clock during reset ...
//

reg	rst_r1, rst_r2;

always @(posedge clk or posedge rst)
	if(rst)		rst_r1 <= #1 1'b1;
	else		rst_r1 <= #1 1'b0;

always @(posedge clk or posedge rst)
	if(rst)		rst_r2 <= #1 1'b1;
	else		rst_r2 <= #1 rst_r1;

////////////////////////////////////////////////////////////////////
//
// Write Logic
//

reg	[6:0]	addr_r;

always @(posedge clk)
	addr_r <= #1 addr[6:0];

assign sel = addr_r[6:3] == reg_select[3:0];

always @(posedge clk)
	if(rst_r2)			csc <= #1 (this_cs[2:0] == `MC_DEF_SEL) ? 
					{26'h0, poc[1:0], 1'b0, poc[3:2], (poc[3:2] != 2'b00)} : 32'h0;
	else
	if(rf_we & sel & !addr_r[2])	csc <= #1 din;

always @(posedge clk)
	if(rst_r2)			tms <= #1 (this_cs[2:0] == `MC_DEF_SEL) ?
						`MC_DEF_POR_TMS : 32'h0;
	else
	if(rf_we & sel & addr_r[2])	tms <= #1 din;

////////////////////////////////////////////////////////////////////
//
// Load Mode Register Request/Ack Logic
//
always @(posedge clk or posedge rst)
	if(rst)		lmr_req_we <= #1 1'b0;
	else		lmr_req_we <= #1 rf_we & sel & addr_r[2];

always @(posedge clk or posedge rst)
	if(rst)		lmr_req <= #1 1'b0;
	else
	if(lmr_req_we & (csc[3:1] == `MC_MEM_TYPE_SDRAM))
			lmr_req <= #1 inited;
	else
	if(lmr_ack)	lmr_req <= #1 1'b0;

////////////////////////////////////////////////////////////////////
//
// Initialize SDRAM Request/Ack & tracking logic
//
always @(posedge clk or posedge rst)
	if(rst)	init_req_we <= #1 1'b0;
	else	init_req_we <= #1 rf_we & sel & !addr_r[2];

always @(posedge clk or posedge rst)
	if(rst)		init_req <= #1 1'b0;
	else
	if(init_req_we & (csc[3:1] == `MC_MEM_TYPE_SDRAM) & csc[0] & !inited)
			init_req <= #1 1'b1;
	else
	if(init_ack)	init_req <= #1 1'b0;

always @(posedge clk or posedge rst)
	if(rst)		inited <= #1 1'b0;
	else
	if(init_ack)	inited <= #1 1'b1;

////////////////////////////////////////////////////////////////////
//
// Chip Select Generation Logic
//

assign cs_d = ((csc[23:16] & csc_mask[7:0]) == (addr[28:21] & csc_mask[7:0])) & csc[0];

assign wp = wb_we_i & csc[8];

assign wp_err = cs_d &  wp;
assign cs     = cs_d & !wp;

endmodule
module mc_cs_rf_dummy(clk, rst, wb_we_i, din, rf_we, addr, csc, tms, poc, csc_mask, cs,
		wp_err, lmr_req, lmr_ack, init_req, init_ack );

parameter	[2:0]	this_cs = 0;

input		clk, rst;
input		wb_we_i;
input	[31:0]	din;
input		rf_we;
input	[31:0]	addr;

output	[31:0]	csc;
output	[31:0]	tms;
input	[31:0]	poc;
input	[31:0]	csc_mask;
output		cs;
output		wp_err;

output		lmr_req;
input		lmr_ack;
output		init_req;
input		init_ack;

assign csc = 32'h0;
assign tms = 32'h0;
assign cs = 1'b0;
assign wp_err = 1'b0;
assign lmr_req = 1'b0;
assign init_req = 1'b0;

endmodule
module add_sub27(add, opa, opb, sum, co);
input		add;
input	[26:0]	opa, opb;
output	[26:0]	sum;
output		co;



assign {co, sum} = add ? (opa + opb) : (opa - opb);

endmodule
module mul_r2(clk, opa, opb, prod);
input		clk;
input	[23:0]	opa, opb;
output	[47:0]	prod;

reg	[47:0]	prod1, prod;

always @(posedge clk)
	prod1 <= #1 opa * opb;

always @(posedge clk)
	prod <= #1 prod1;

endmodule
module div_r2(clk, opa, opb, quo, rem);
input		clk;
input	[49:0]	opa;
input	[23:0]	opb;
output	[49:0]	quo, rem;

reg	[49:0]	quo, rem, quo1, remainder;

always @(posedge clk)
	quo1 <= #1 opa / opb;

always @(posedge clk)
	quo <= #1 quo1;

always @(posedge clk)
	remainder <= #1 opa % opb;

always @(posedge clk)
	rem <= #1 remainder;

endmodule
module aes128_keyex(
	input 				i_clk,
	input 				i_rst,
	input  [127:0]	 	i_key,		//key
	input 				i_key_en,	//key init flag
	output [128*11-1:0]	o_exkey,  	//round key
	output 				o_key_ok,  	//key init ok
	output				o_sbox_use,
	output [31:0]		o_sbox_din,
	input  [31:0]		i_sbox_dout
	);
	
	localparam DLY = 1;
	
	wire   [127:0]	s_key;
	reg    [127:0]	r_key;
	reg	  [1279:0]	r_exkey;
	reg 	[3:0]	r_count;
	reg 			r_key_ok;
	wire 			s_busy;
	wire 	[127:0]	s_exk;
	reg 	[31:0]	r_rcon;
	
	//round left shift
	function [31:0] ROL;
		input [31:0] D;
		begin
			ROL = {D[23:0],D[31:24]};
		end
	endfunction
	
	always@(*) begin
		case(r_count) 
			4'd0: r_rcon = 32'h01000000;
			4'd1: r_rcon = 32'h02000000;
			4'd2: r_rcon = 32'h04000000;
			4'd3: r_rcon = 32'h08000000;
			4'd4: r_rcon = 32'h10000000;
			4'd5: r_rcon = 32'h20000000;
			4'd6: r_rcon = 32'h40000000;
			4'd7: r_rcon = 32'h80000000;
			4'd8: r_rcon = 32'h1B000000;
			4'd9: r_rcon = 32'h36000000;
			default: r_rcon = 32'b0;
		endcase
	end
	
	assign s_key = i_key_en ? i_key : r_key;
	//left shift 1|2 bits
	assign o_sbox_use = s_busy;
	assign o_sbox_din = ROL(s_key[31:0]);
	//
	assign s_exk[127:96] = s_key[127:96]^i_sbox_dout^r_rcon;
	assign s_exk[95:64] = s_key[95:64]^s_exk[127:96];
	assign s_exk[63:32] = s_key[63:32]^s_exk[95:64];
	assign s_exk[31:0] = s_key[31:0]^s_exk[63:32];
	
	always@(posedge i_clk or posedge i_rst) begin
		if(i_rst)
			r_key <= #DLY 128'b0;
		else if(s_busy)
			r_key <= #DLY s_exk;
	end	
	
	always@(posedge i_clk or posedge i_rst) begin
		if(i_rst) begin
			r_exkey <= #DLY 1280'b0;
		end else if(s_busy)begin
			r_exkey <= #DLY {r_exkey[128*9-1:0],s_exk};
		end
	end	
	
	always@(posedge i_clk or posedge i_rst) begin
		if(i_rst)
			r_count <= #DLY 4'd0;
		else if(i_key_en)
			r_count <= #DLY 4'd1;
		else if(r_count ==4'd9)
			r_count <= #DLY 4'd0;
		else if(r_count!=4'd0)
			r_count <= #DLY r_count + 4'd1;
	end
	
	assign s_busy = ((r_count!=5'd0)||(i_key_en==1'b1)) ? 1'b1 : 1'b0;
	
	always@(posedge i_clk or posedge i_rst) begin
		if(i_rst)
			r_key_ok <= #DLY 1'b0;
		else if(r_count==4'd9)
			r_key_ok <= #DLY 1'b1;
		else if(i_key_en==1'b1)
			r_key_ok <= #DLY 1'b0;
	end

	assign o_key_ok = r_key_ok&(~i_key_en);
	assign o_exkey = {i_key,r_exkey};	
	
endmodule
module aes128_core(
    input           i_clk,
    input           i_rst,
    input           i_flag,    //1-encrypt,0-decrypt
    input  [127:0]  i_key,
    input           i_key_en,  //1-key init start
	output 			o_key_ok,  //1-key init done
    input  [127:0]  i_din,
    input           i_din_en,
    output [127:0]  o_dout,
    output          o_dout_en
    );
 
	wire  [128*11-1:0] 	s_exkey;
	//KeyExpand
	wire        		s_sbox_use_ke;
	wire  [31:0]		s_sbox_din_ke;
	wire  [31:0]		s_sbox_dout_ke;
	//DataProcess
	wire  [127:0]		s_sbox_din_dp;
	wire  [127:0]		s_sbox_dout_dp;
	//SubByte S-Box
	wire  [127:0]	   	s_sbox_din;
	wire  [127:0]	   	s_sbox_dout;
	wire  [127:0]		s_sbox_dout_p;
	wire  [127:0]		s_sbox_dout_n;
	//
	genvar i;	
 
	//key expand
	aes128_keyex u_keyex(
	.i_clk		(i_clk			),
	.i_rst		(i_rst			),
	.i_key		(i_key			),
	.i_key_en	(i_key_en		),
	.o_exkey	(s_exkey		),
	.o_key_ok	(o_key_ok		),
	.o_sbox_use (s_sbox_use_ke	),
	.o_sbox_din	(s_sbox_din_ke 	),
	.i_sbox_dout(s_sbox_dout_ke	)
	);

	//data encrypt or decrypt
	aes128_dpc u_dpc(
	.i_clk		(i_clk			),
	.i_rst		(i_rst			),	
	.i_flag		(i_flag			),
	.i_keyex	(s_exkey		),
    .i_din		(i_din			),
    .i_din_en	(i_din_en		),
    .o_dout		(o_dout			),
    .o_dout_en	(o_dout_en		),
	.o_sbox_din	(s_sbox_din_dp 	),
	.i_sbox_dout(s_sbox_dout_dp	)	
	);	
	
	assign s_sbox_din = s_sbox_use_ke ? {96'b0,s_sbox_din_ke} : s_sbox_din_dp;
	assign s_sbox_dout_ke = s_sbox_dout_p[31:0];
	assign s_sbox_dout_dp = i_flag ? s_sbox_dout_p:s_sbox_dout_n;
	
	generate 
		for(i=0;i<16;i=i+1) begin: INST_SBOX_P
			aes_sbox_p u_sbox_p(
			.din	(s_sbox_din[8*i+7:8*i]	 ),
			.dout	(s_sbox_dout_p[8*i+7:8*i])
			);
		end
		
		for(i=0;i<16;i=i+1) begin: INST_SBOX_N
			aes_sbox_n u_sbox_n(
			.din	(s_sbox_din[8*i+7:8*i]	 ),
			.dout	(s_sbox_dout_n[8*i+7:8*i])
			);
		end		
	endgenerate
	
	
endmodule
module aes_mixcol_w(
	input	[31:0]	i_din,
	output 	[31:0]	o_dout_x,
	output 	[31:0]	o_dout_y);

	wire [7:0]	s_a,s_b,s_c,s_d;
	wire [7:0]	s_x1,s_x2,s_x3,s_x4;
	wire [7:0]	s_y1,s_y2,s_y3,s_y4;
	
	assign s_a = i_din[31:24];
	assign s_b = i_din[23:16];
	assign s_c = i_din[15:8];
	assign s_d = i_din[7:0];
	
	aes_mixcol_b u_bm1 (.i_a(s_a), .i_b(s_b), .i_c(s_c), .i_d(s_d), .o_x(s_x1), .o_y(s_y1));
	aes_mixcol_b u_bm2 (.i_a(s_b), .i_b(s_c), .i_c(s_d), .i_d(s_a), .o_x(s_x2), .o_y(s_y2));
	aes_mixcol_b u_bm3 (.i_a(s_c), .i_b(s_d), .i_c(s_a), .i_d(s_b), .o_x(s_x3), .o_y(s_y3));
	aes_mixcol_b u_bm4 (.i_a(s_d), .i_b(s_a), .i_c(s_b), .i_d(s_c), .o_x(s_x4), .o_y(s_y4));
		
	assign o_dout_x = {s_x1,s_x2,s_x3,s_x4};
	assign o_dout_y = {s_y1,s_y2,s_y3,s_y4};
	
endmodule
module aes_mixcol_b(
	input	[7:0]	i_a,
	input	[7:0]	i_b,
	input	[7:0]	i_c,
	input 	[7:0]	i_d,
	output 	[7:0]	o_x,
	output 	[7:0]	o_y);

	wire 	[7:0] 	s_w1,s_w2,s_w3,s_w4;
	wire 	[7:0]	s_w5,s_w6,s_w7,s_w8;
	
	function [7:0] xtime;
	  input [7:0] in;
	  reg [3:0] xtime_t;
	  begin
		xtime[7:5] = in[6:4];
		xtime_t[3] = in[7];
		xtime_t[2] = in[7];
		xtime_t[1] = 0;
		xtime_t[0] = in[7];
		xtime[4:1] =xtime_t^in[3:0];
		xtime[0] = in[7];
	  end
	endfunction

	assign s_w1 = i_a ^i_b;
	assign s_w2 = i_a ^i_c;
	assign s_w3 = i_c ^i_d;
	assign s_w4 = xtime(s_w1);
	assign s_w5 = xtime(s_w3);
	assign s_w6 = s_w2 ^s_w4 ^s_w5;
	assign s_w7 = xtime(s_w6);
	assign s_w8 = xtime(s_w7);

	assign o_x = i_b^s_w3^s_w4;
	assign o_y = s_w8^o_x;

endmodule
module wb_dma_inc30r(clk, in, out);
input		clk;
input	[29:0]	in;
output	[29:0]	out;

// INC30_CENTER indicates the center bit of the 30 bit incrementor
// so it can be easily manually optimized for best performance
parameter	INC30_CENTER = 16;

reg	[INC30_CENTER:0]	out_r;

always @(posedge clk)
	out_r <= #1 in[(INC30_CENTER - 1):0] + 1;

assign out[29:INC30_CENTER] = in[29:INC30_CENTER] + out_r[INC30_CENTER];
assign out[(INC30_CENTER - 1):0]  = out_r;

endmodule
module wb_dma_wb_mast(clk, rst,

	wb_data_i, wb_data_o, wb_addr_o, wb_sel_o, wb_we_o, wb_cyc_o,
	wb_stb_o, wb_ack_i, wb_err_i, wb_rty_i,

	mast_go, mast_we, mast_adr, mast_din, mast_dout, mast_err,
	mast_drdy, mast_wait,

	pt_sel, mast_pt_in, mast_pt_out
	);

input		clk, rst;

// --------------------------------------
// WISHBONE INTERFACE 

input	[31:0]	wb_data_i;
output	[31:0]	wb_data_o;
output	[31:0]	wb_addr_o;
output	[3:0]	wb_sel_o;
output		wb_we_o;
output		wb_cyc_o;
output		wb_stb_o;
input		wb_ack_i;
input		wb_err_i;
input		wb_rty_i;

// --------------------------------------
// INTERNAL DMA INTERFACE 
input		mast_go;	// Perform a Master Cycle (as long as this
				// line is asserted)
input		mast_we;	// Read/Write
input	[31:0]	mast_adr;	// Address for the transfer
input	[31:0]	mast_din;	// Internal Input Data
output	[31:0]	mast_dout;	// Internal Output Data
output		mast_err;	// Indicates an error has occurred

output		mast_drdy;	// Indicated that either data is available
				// during a read, or that the master can accept
				// the next data during a write
input		mast_wait;	// Tells the master to insert wait cycles
				// because data can not be accepted/provided

// Pass Through Interface
input		pt_sel;		// Pass Through Mode Selected
input	[70:0]	mast_pt_in;	// Grouped WISHBONE inputs
output	[34:0]	mast_pt_out;	// Grouped WISHBONE outputs

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

reg		mast_cyc, mast_stb;
reg		mast_we_r;
reg	[3:0]	mast_be;
reg	[31:0]	mast_dout;

////////////////////////////////////////////////////////////////////
//
// Pass-Through Interface
//

assign {wb_data_o, wb_addr_o, wb_sel_o, wb_we_o, wb_cyc_o, wb_stb_o} =
	pt_sel ? mast_pt_in :
	{mast_din, mast_adr, mast_be, mast_we_r, mast_cyc, mast_stb};

assign mast_pt_out = {wb_data_i, wb_ack_i, wb_err_i, wb_rty_i};

////////////////////////////////////////////////////////////////////
//
// DMA Engine Interface
//

always @(posedge clk)
	if(wb_ack_i)	mast_dout <= #1 wb_data_i;

always @(posedge clk)
	mast_be <= #1 4'hf;

always @(posedge clk)
	mast_we_r <= #1 mast_we;

always @(posedge clk)
	mast_cyc <= #1 mast_go;

always @(posedge clk)
	mast_stb <= #1 mast_go & !mast_wait; 

assign mast_drdy = wb_ack_i;
assign mast_err  = wb_err_i;

endmodule
module wb_dma_wb_slv(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, wb_rty_o,

	// This is the register File Interface
	slv_adr, slv_din, slv_dout, slv_re, slv_we,

	// Pass through Interface
	pt_sel, slv_pt_out, slv_pt_in

	);

parameter	rf_addr = 0;

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;
output		wb_rty_o;

// This is the register File Interface
output	[31:0]	slv_adr;	// Slave Address
input	[31:0]	slv_din;	// Slave Input Data
output	[31:0]	slv_dout;	// Slave Output Data
output		slv_re;		// Slave Read Enable
output		slv_we;		// Slave Write Enable

// Pass through Interface
output		pt_sel;		// Pass Through Mode Active
output	[70:0]	slv_pt_out;	// Grouped WISHBONE out signals
input	[34:0]	slv_pt_in;	// Grouped WISHBONE in signals

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

reg		slv_re, slv_we;
wire		rf_sel;
reg		rf_ack;
reg	[31:0]	slv_adr, slv_dout;

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

assign rf_sel = `WDMA_REG_SEL ;

////////////////////////////////////////////////////////////////////
//
// Pass Through Logic
//

//assign pt_sel = !rf_sel;
assign pt_sel = !rf_sel & wb_cyc_i;

assign slv_pt_out = {wb_data_i, wb_addr_i, wb_sel_i, wb_we_i, wb_cyc_i, wb_stb_i};
assign {wb_data_o, wb_ack_o, wb_err_o, wb_rty_o} = pt_sel ? slv_pt_in :
	{slv_din, rf_ack, 1'b0, 1'b0};

////////////////////////////////////////////////////////////////////
//
// Register File Logic
//

always @(posedge clk)
	slv_adr <= #1 wb_addr_i;

always @(posedge clk)
	slv_re <= #1 rf_sel & wb_cyc_i & wb_stb_i & !wb_we_i & !rf_ack & !slv_re;

always @(posedge clk)
	slv_we <= #1 rf_sel & wb_cyc_i & wb_stb_i &  wb_we_i & !rf_ack;

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

always @(posedge clk)
	rf_ack <= #1 (slv_re | slv_we) & wb_cyc_i & wb_stb_i & !rf_ack ;

endmodule
module wb_dma_pri_enc_sub(valid, pri_in, pri_out);

parameter [3:0]	ch_conf = 4'b0000;
parameter [1:0]	pri_sel = 2'd0;

input		valid;
input	[2:0]	pri_in;
output	[7:0]	pri_out;

wire	[7:0]	pri_out;
reg	[7:0]	pri_out_d;
reg	[7:0]	pri_out_d0;
reg	[7:0]	pri_out_d1;
reg	[7:0]	pri_out_d2;

assign pri_out = ch_conf[0] ? pri_out_d : 8'h0;

// Select Configured Priority
always @(pri_sel or pri_out_d0 or pri_out_d1 or  pri_out_d2)
	case(pri_sel)		// synopsys parallel_case full_case
	   2'd0: pri_out_d = pri_out_d0;
	   2'd1: pri_out_d = pri_out_d1;
	   2'd2: pri_out_d = pri_out_d2;
	endcase

// 8 Priority Levels
always @(valid or pri_in)
	if(!valid)		pri_out_d2 = 8'b0000_0001;
	else
	if(pri_in==3'h0)	pri_out_d2 = 8'b0000_0001;
	else
	if(pri_in==3'h1)	pri_out_d2 = 8'b0000_0010;
	else
	if(pri_in==3'h2)	pri_out_d2 = 8'b0000_0100;
	else
	if(pri_in==3'h3)	pri_out_d2 = 8'b0000_1000;
	else
	if(pri_in==3'h4)	pri_out_d2 = 8'b0001_0000;
	else
	if(pri_in==3'h5)	pri_out_d2 = 8'b0010_0000;
	else
	if(pri_in==3'h6)	pri_out_d2 = 8'b0100_0000;
	else			pri_out_d2 = 8'b1000_0000;

// 4 Priority Levels
always @(valid or pri_in)
	if(!valid)		pri_out_d1 = 8'b0000_0001;
	else
	if(pri_in==3'h0)	pri_out_d1 = 8'b0000_0001;
	else
	if(pri_in==3'h1)	pri_out_d1 = 8'b0000_0010;
	else
	if(pri_in==3'h2)	pri_out_d1 = 8'b0000_0100;
	else			pri_out_d1 = 8'b0000_1000;

// 2 Priority Levels
always @(valid or pri_in)
	if(!valid)		pri_out_d0 = 8'b0000_0001;
	else
	if(pri_in==3'h0)	pri_out_d0 = 8'b0000_0001;
	else			pri_out_d0 = 8'b0000_0010;

endmodule
module div_su(clk, ena, z, d, q, s, div0, ovf);

	//
	// parameters
	//
	parameter z_width = 16;
	parameter d_width = z_width /2;

	//
	// inputs & outputs
	//
	input clk;              // system clock
	input ena;              // clock enable

	input  [z_width-1:0] z; // divident
	input  [d_width-1:0] d; // divisor
	output [d_width  :0] q; // quotient
	output [d_width-1:0] s; // remainder
	output div0;
	output ovf;

	reg [d_width :0] q;
	reg [d_width-1:0] s;
	reg div0;
	reg ovf;

	//
	// variables
	//
	reg [z_width -1:0] iz;
	reg [d_width -1:0] id;
	reg [d_width +1:0] spipe;

	wire [d_width -1:0] iq, is;
	wire                idiv0, iovf;

	//
	// module body
	//

	// delay d
	always @(posedge clk)
	  if (ena)
	    id <= #1 d;

	// check z, take abs value
	always @(posedge clk)
	  if (ena)
	    if (z[z_width-1])
	       iz <= #1 ~z +1'h1;
	    else
	       iz <= #1 z;

	// generate spipe (sign bit pipe)
	integer n;
	always @(posedge clk)
	  if(ena)
	  begin
	      spipe[0] <= #1 z[z_width-1];

	      for(n=1; n <= d_width+1; n=n+1)
	         spipe[n] <= #1 spipe[n-1];
	  end

	// hookup non-restoring divider
	div_uu #(z_width, d_width)
	divider (
		.clk(clk),
		.ena(ena),
		.z(iz),
		.d(id),
		.q(iq),
		.s(is),
		.div0(idiv0),
		.ovf(iovf)
	);

	// correct divider results if 'd' was negative
	always @(posedge clk)
	  if(ena)
	    if(spipe[d_width+1])
	    begin
	        q <= #1 (~iq) + 1'h1;
	        s <= #1 (~is) + 1'h1;
	    end
	    else
	    begin
	        q <= #1 {1'b0, iq};
	        s <= #1 {1'b0, is};
	    end

	// delay flags same as results
	always @(posedge clk)
	  if(ena)
	  begin
	      div0 <= #1 idiv0;
	      ovf  <= #1 iovf;
	  end
endmodule
module dctub(clk, ena, ddgo, x, y, ddin,
		dout0, dout1, dout2, dout3, dout4, dout5, dout6, dout7);

	parameter coef_width = 16;
	parameter di_width = 8;
	parameter [2:0] v = 3'h0;

	//
	// inputs & outputs
	//
	input clk;
	input ena;
	input ddgo;               // double delayed go strobe
	input [2:0] x, y;

	input  [di_width:1] ddin; // delayed data input
	output [11:0] dout0, dout1, dout2, dout3, dout4, dout5, dout6, dout7;

	//
	// module body
	//

	// Hookup DCT units
	dctu #(coef_width, di_width, v, 3'h0)
	dct_unit_0 (
		.clk(clk),
		.ena(ena),
		.ddgo(ddgo),
		.x(x),
		.y(y),
		.ddin(ddin),
		.dout(dout0)
	);

	dctu #(coef_width, di_width, v, 3'h1)
	dct_unit_1 (
		.clk(clk),
		.ena(ena),
		.ddgo(ddgo),
		.x(x),
		.y(y),
		.ddin(ddin),
		.dout(dout1)
	);

	dctu #(coef_width, di_width, v, 3'h2)
	dct_unit_2 (
		.clk(clk),
		.ena(ena),
		.ddgo(ddgo),
		.x(x),
		.y(y),
		.ddin(ddin),
		.dout(dout2)
	);

	dctu #(coef_width, di_width, v, 3'h3)
	dct_unit_3 (
		.clk(clk),
		.ena(ena),
		.ddgo(ddgo),
		.x(x),
		.y(y),
		.ddin(ddin),
		.dout(dout3)
	);

	dctu #(coef_width, di_width, v, 3'h4)
	dct_unit_4 (
		.clk(clk),
		.ena(ena),
		.ddgo(ddgo),
		.x(x),
		.y(y),
		.ddin(ddin),
		.dout(dout4)
	);

	dctu #(coef_width, di_width, v, 3'h5)
	dct_unit_5 (
		.clk(clk),
		.ena(ena),
		.ddgo(ddgo),
		.x(x),
		.y(y),
		.ddin(ddin),
		.dout(dout5)
	);

	dctu #(coef_width, di_width, v, 3'h6)
	dct_unit_6 (
		.clk(clk),
		.ena(ena),
		.ddgo(ddgo),
		.x(x),
		.y(y),
		.ddin(ddin),
		.dout(dout6)
	);

	dctu #(coef_width, di_width, v, 3'h7)
	dct_unit_7 (
		.clk(clk),
		.ena(ena),
		.ddgo(ddgo),
		.x(x),
		.y(y),
		.ddin(ddin),
		.dout(dout7)
	);
endmodule
module jpeg_rle(clk, rst, ena, dstrb, din, size, rlen, amp, douten, bstart);

	//
	// parameters
	//

	//
	// inputs & outputs
	//
	input         clk;     // system clock
	input         rst;     // asynchronous reset
	input         ena;     // clock enable
	input         dstrb;
	input  [11:0] din;     // data input

	output [ 3:0] size;    // size
	output [ 3:0] rlen;    // run-length
	output [11:0] amp;     // amplitude
	output        douten;  // data output enable
	output        bstart;  // block start

	//
	// variables
	//

	wire [ 3:0] rle_rlen, rz1_rlen, rz2_rlen, rz3_rlen, rz4_rlen;
	wire [ 3:0] rle_size, rz1_size, rz2_size, rz3_size, rz4_size;
	wire [11:0] rle_amp,  rz1_amp,  rz2_amp,  rz3_amp,  rz4_amp;
	wire        rle_den,  rz1_den,  rz2_den,  rz3_den,  rz4_den;
	wire        rle_dc,   rz1_dc,   rz2_dc,   rz3_dc,   rz4_dc;

	//
	// module body
	//

	reg ddstrb;
	always @(posedge clk)
	  ddstrb <= #1 dstrb;

	// generate run-length encoded signals
	jpeg_rle1 rle(
		.clk(clk),
		.rst(rst),
		.ena(ena),
		.go(ddstrb),
		.din(din),
		.rlen(rle_rlen),
		.size(rle_size),
		.amp(rle_amp),
		.den(rle_den),
		.dcterm(rle_dc)
	);

	// Find (15,0) (0,0) sequences and replace by (0,0)
	// There can be max. 4 (15,0) sequences in a row

	// step1
	jpeg_rzs rz1(
		.clk(clk),
		.rst(rst),
		.ena(ena),
		.rleni(rle_rlen),
		.sizei(rle_size),
		.ampi(rle_amp),
		.deni(rle_den),
		.dci(rle_dc),
		.rleno(rz1_rlen),
		.sizeo(rz1_size),
		.ampo(rz1_amp),
		.deno(rz1_den),
		.dco(rz1_dc)
	);

	// step2
	jpeg_rzs rz2(
		.clk(clk),
		.rst(rst),
		.ena(ena),
		.rleni(rz1_rlen),
		.sizei(rz1_size),
		.ampi(rz1_amp),
		.deni(rz1_den),
		.dci(rz1_dc),
		.rleno(rz2_rlen),
		.sizeo(rz2_size),
		.ampo(rz2_amp),
		.deno(rz2_den),
		.dco(rz2_dc)
	);

	// step3
	jpeg_rzs rz3(
		.clk(clk),
		.rst(rst),
		.ena(ena),
		.rleni(rz2_rlen),
		.sizei(rz2_size),
		.ampi(rz2_amp),
		.deni(rz2_den),
		.dci(rz2_dc),
		.rleno(rz3_rlen),
		.sizeo(rz3_size),
		.ampo(rz3_amp),
		.deno(rz3_den),
		.dco(rz3_dc)
	);

	// step4
	jpeg_rzs rz4(
		.clk(clk),
		.rst(rst),
		.ena(ena),
		.rleni(rz3_rlen),
		.sizei(rz3_size),
		.ampi(rz3_amp),
		.deni(rz3_den),
		.dci(rz3_dc),
		.rleno(rz4_rlen),
		.sizeo(rz4_size),
		.ampo(rz4_amp),
		.deno(rz4_den),
		.dco(rz4_dc)
	);


	// assign outputs
	assign rlen   = rz4_rlen;
	assign size   = rz4_size;
	assign amp    = rz4_amp;
	assign douten = rz4_den;
	assign bstart = rz4_dc;
endmodule
module jpeg_qnr(clk, ena, rst, dstrb, din, qnt_val, qnt_cnt, dout, douten);

	//
	// parameters
	//
	parameter d_width = 12;
	parameter z_width = 2 * d_width;

	//
	// inputs & outputs
	//
	input clk;                    // system clock
	input ena;                    // clock enable
	input rst;                    // asynchronous active low reset

	input                dstrb;   // present dstrb 1clk cycle before din
	input  [d_width-1:0] din;     // data input
	input  [ 7:0]        qnt_val; // quantization value

	output [ 5:0]        qnt_cnt; // sample number (get quantization value qnt_cnt)
	output [10:0]        dout;    // data output
	output               douten;

	//
	// variables
	//
	wire [z_width-1:0] iz; // intermediate divident value
	wire [d_width-1:0] id; // intermediate dividor value
	wire [d_width  :0] iq; // intermediate result divider
	reg  [d_width  :0] rq; // rounded q-value
	reg  [d_width+3:0] dep;// data enable pipeline

	// generate sample counter
	reg  [5:0] qnt_cnt;
	wire       dcnt     = &qnt_cnt;

	always @(posedge clk or negedge rst)
	  if (~rst)
	     qnt_cnt <= #1 6'h0;
	  else if (dstrb)
	     qnt_cnt <= #1 6'h0;
	  else if (ena)
	     qnt_cnt <= #1 qnt_cnt + 6'h1;

	// generate intermediate dividor/divident values
	assign id = { {(d_width - 8){1'b0}}, qnt_val};
	assign iz = { {(z_width - d_width){din[d_width-1]}}, din};

	// hookup division unit
	div_su #(z_width)
	divider (
		.clk(clk),
		.ena(ena),
		.z(iz),
		.d(id),
		.q(iq),
		.s(),
		.div0(),
		.ovf()
	);

	// round result to the nearest integer
	always @(posedge clk)
	  if (ena)
	    if (iq[0])
	      if (iq[d_width])
	         rq <= #1 iq - 1'h1;
	      else
	         rq <= #1 iq + 1'h1;
	    else
	       rq <= #1 iq;

	// assign dout signal
	assign dout = rq[d_width -1: d_width-11];


	// generate data-out enable signal
	// This is a pipeline, data is not dependant on sample-count
	integer n;
	always @(posedge clk or negedge rst)
	  if (!rst)
	     dep <= #1 0;
	  else if(ena)
	     begin
	         dep[0] <= #1 dstrb;

	         for (n=1; n <= d_width +3; n = n +1)
	             dep[n] <= #1 dep[n-1];
	     end

	assign douten = dep[d_width +3];
endmodule
module dctu(clk, ena, ddgo, x, y, ddin, dout);

	parameter coef_width = 16;
	parameter di_width = 8;
	parameter [2:0] v = 0;
	parameter [2:0] u = 0;

	//
	// inputs & outputs
	//

	input clk;
	input ena;
	input ddgo;               // double delayed go signal
	input [2:0] x, y;

	input  [di_width:1] ddin; // delayed data input
	output [11:0] dout;

	//
	// variables
	//
	reg [      31:0] coef;

	wire [coef_width +10:0] result;
	`include "dct_cos_table.v"
	//
	// module body
	//

	// hookup cosine-table
	always @(posedge clk)
	  if(ena)
	    coef <= #1 dct_cos_table(x, y, u, v);

	// hookup dct-mac unit
	dct_mac #(8, coef_width)
	macu (
		.clk(clk),
		.ena(ena),
		.dclr(ddgo),
		.din(ddin),
		.coef( coef[31:31 -coef_width +1] ),
		.result(result)
	);

	assign dout = result[coef_width +10: coef_width -1];
endmodule
module ac97_cra(clk, rst,

		crac_we, crac_din, crac_out,
		crac_wr_done, crac_rd_done,

		valid, out_slt1, out_slt2,
		in_slt2,

		crac_valid, crac_wr
		);

input		clk, rst;
input		crac_we;
output	[15:0]	crac_din;
input	[31:0]	crac_out;
output		crac_wr_done, crac_rd_done;

input		valid;
output	[19:0]	out_slt1;
output	[19:0]	out_slt2;
input	[19:0]	in_slt2;

output		crac_valid;
output		crac_wr;


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

reg		crac_wr;
reg		crac_rd;
reg		crac_rd_done;
reg	[15:0]	crac_din;
reg		crac_we_r;
reg		valid_r;
wire		valid_ne;
wire		valid_pe;
reg		rdd1, rdd2, rdd3;

////////////////////////////////////////////////////////////////////
//
// Codec Register Data Path
//

// Control
assign out_slt1[19]    = crac_out[31];
assign out_slt1[18:12] = crac_out[22:16];
assign out_slt1[11:0]  = 12'h0;

// Write Data
assign out_slt2[19:4] = crac_out[15:0];
assign out_slt2[3:0] = 4'h0;

// Read Data
always @(posedge clk or negedge rst)
   begin
	if(!rst)		crac_din <= #1 16'h0;
	else
	if(crac_rd_done)	crac_din <= #1 in_slt2[19:4];
   end

////////////////////////////////////////////////////////////////////
//
// Codec Register Access Tracking
//

assign crac_valid = crac_wr | crac_rd;

always @(posedge clk)
	crac_we_r <= #1 crac_we;

always @(posedge clk or negedge rst)
	if(!rst)			crac_wr <= #1 1'b0;
	else
	if(crac_we_r & !crac_out[31])	crac_wr <= #1 1'b1;
	else
	if(valid_ne)			crac_wr <= #1 1'b0;

assign crac_wr_done = crac_wr & valid_ne;

always @(posedge clk or negedge rst)
	if(!rst)			crac_rd <= #1 1'b0;
	else
	if(crac_we_r & crac_out[31])	crac_rd <= #1 1'b1;
	else
	if(rdd1 & valid_pe)		crac_rd <= #1 1'b0;

always @(posedge clk or negedge rst)
	if(!rst)			rdd1 <= #1 1'b0;
	else
	if(crac_rd & valid_ne)		rdd1 <= #1 1'b1;
	else
	if(!crac_rd)			rdd1 <= #1 1'b0;

always @(posedge clk or negedge rst)
	if(!rst)					rdd2 <= #1 1'b0;
	else
	if( (crac_rd & valid_ne) | (!rdd3 & rdd2) )	rdd2 <= #1 1'b1;
	else
	if(crac_rd_done)				rdd2 <= #1 1'b0;

always @(posedge clk or negedge rst)
	if(!rst)			rdd3 <= #1 1'b0;
	else
	if(rdd2 & valid_pe)		rdd3 <= #1 1'b1;
	else
	if(crac_rd_done)		rdd3 <= #1 1'b0;

always @(posedge clk)
	crac_rd_done <= #1 rdd3 & valid_pe;

always @(posedge clk)
	valid_r <= #1 valid;

assign valid_ne = !valid & valid_r;

assign valid_pe = valid & !valid_r;

endmodule
module ac97_rst(clk, rst, rst_force, ps_ce, ac97_rst_);
input		clk, rst;
input		rst_force;
output		ps_ce;
output		ac97_rst_;

reg		ac97_rst_;
reg	[2:0]	cnt;
wire		ce;
wire		to;
reg	[5:0]	ps_cnt;
wire		ps_ce;

always @(posedge clk or negedge rst)
	if(!rst)	ac97_rst_ <= #1 0;
	else
	if(rst_force)	ac97_rst_ <= #1 0;
	else
	if(to)		ac97_rst_ <= #1 1;

assign to = (cnt == `AC97_RST_DEL);

always @(posedge clk or negedge rst)
	if(!rst)	cnt <= #1 0;
	else
	if(rst_force)	cnt <= #1 0;
	else
	if(ce)		cnt <= #1 cnt + 1;

assign ce = ps_ce & (cnt != `AC97_RST_DEL);

always @(posedge clk or negedge rst)
	if(!rst)		ps_cnt <= #1 0;
	else
	if(ps_ce | rst_force)	ps_cnt <= #1 0;
	else			ps_cnt <= #1 ps_cnt + 1;

assign ps_ce = (ps_cnt == `AC97_250_PS);

endmodule
module ac97_sout(clk, rst,

	so_ld, slt0, slt1, slt2, slt3, slt4,
	slt6, slt7, slt8, slt9,

	sdata_out
	);

input		clk, rst;

// --------------------------------------
// Misc Signals
input		so_ld;
input	[15:0]	slt0;
input	[19:0]	slt1;
input	[19:0]	slt2;
input	[19:0]	slt3;
input	[19:0]	slt4;
input	[19:0]	slt6;
input	[19:0]	slt7;
input	[19:0]	slt8;
input	[19:0]	slt9;

// --------------------------------------
// AC97 Codec Interface
output		sdata_out;

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

wire		sdata_out;

reg	[15:0]	slt0_r;
reg	[19:0]	slt1_r;
reg	[19:0]	slt2_r;
reg	[19:0]	slt3_r;
reg	[19:0]	slt4_r;
reg	[19:0]	slt5_r;
reg	[19:0]	slt6_r;
reg	[19:0]	slt7_r;
reg	[19:0]	slt8_r;
reg	[19:0]	slt9_r;
reg	[19:0]	slt10_r;
reg	[19:0]	slt11_r;
reg	[19:0]	slt12_r;

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

////////////////////////////////////////////////////////////////////
//
// Serial Shift Register
//

assign	sdata_out = slt0_r[15];

always @(posedge clk)
	if(so_ld)	slt0_r <= #1 slt0;
	else		slt0_r <= #1 {slt0_r[14:0], slt1_r[19]};

always @(posedge clk)
	if(so_ld)	slt1_r <= #1 slt1;
	else		slt1_r <= #1 {slt1_r[18:0], slt2_r[19]};

always @(posedge clk)
	if(so_ld)	slt2_r <= #1 slt2;
	else		slt2_r <= #1 {slt2_r[18:0], slt3_r[19]};

always @(posedge clk)
	if(so_ld)	slt3_r <= #1 slt3;
	else		slt3_r <= #1 {slt3_r[18:0], slt4_r[19]};

always @(posedge clk)
	if(so_ld)	slt4_r <= #1 slt4;
	else		slt4_r <= #1 {slt4_r[18:0], slt5_r[19]};

always @(posedge clk)
	if(so_ld)	slt5_r <= #1 20'h0;
	else		slt5_r <= #1 {slt5_r[18:0], slt6_r[19]};

always @(posedge clk)
	if(so_ld)	slt6_r <= #1 slt6;
	else		slt6_r <= #1 {slt6_r[18:0], slt7_r[19]};

always @(posedge clk)
	if(so_ld)	slt7_r <= #1 slt7;
	else		slt7_r <= #1 {slt7_r[18:0], slt8_r[19]};

always @(posedge clk)
	if(so_ld)	slt8_r <= #1 slt8;
	else		slt8_r <= #1 {slt8_r[18:0], slt9_r[19]};

always @(posedge clk)
	if(so_ld)	slt9_r <= #1 slt9;
	else		slt9_r <= #1 {slt9_r[18:0], slt10_r[19]};

always @(posedge clk)
	if(so_ld)	slt10_r <= #1 20'h0;
	else		slt10_r <= #1 {slt10_r[18:0], slt11_r[19]};

always @(posedge clk)
	if(so_ld)	slt11_r <= #1 20'h0;
	else		slt11_r <= #1 {slt11_r[18:0], slt12_r[19]};

always @(posedge clk)
	if(so_ld)	slt12_r <= #1 20'h0;
	else		slt12_r <= #1 {slt12_r[18:0], 1'b0 };

endmodule
module ac97_sin(clk, rst,

	out_le, slt0, slt1, slt2, slt3, slt4,
	slt6, 

	sdata_in
	);

input		clk, rst;

// --------------------------------------
// Misc Signals
input	[5:0]	out_le;
output	[15:0]	slt0;
output	[19:0]	slt1;
output	[19:0]	slt2;
output	[19:0]	slt3;
output	[19:0]	slt4;
output	[19:0]	slt6;

// --------------------------------------
// AC97 Codec Interface
input		sdata_in;

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

reg		sdata_in_r;
reg	[19:0]	sr;

reg	[15:0]	slt0;
reg	[19:0]	slt1;
reg	[19:0]	slt2;
reg	[19:0]	slt3;
reg	[19:0]	slt4;
reg	[19:0]	slt6;

////////////////////////////////////////////////////////////////////
//
// Output Registers
//

always @(posedge clk)
	if(out_le[0])	slt0 <= #1 sr[15:0];

always @(posedge clk)
	if(out_le[1])	slt1 <= #1 sr;

always @(posedge clk)
	if(out_le[2])	slt2 <= #1 sr;

always @(posedge clk)
	if(out_le[3])	slt3 <= #1 sr;

always @(posedge clk)
	if(out_le[4])	slt4 <= #1 sr;

always @(posedge clk)
	if(out_le[5])	slt6 <= #1 sr;

////////////////////////////////////////////////////////////////////
//
// Serial Shift Register
//

always @(negedge clk)
	sdata_in_r <= #1 sdata_in;

always @(posedge clk)
	sr <= #1 {sr[18:0], sdata_in_r };

endmodule
module ac97_dma_if(clk, rst,
		o3_status, o4_status, o6_status, o7_status, o8_status, o9_status,
		o3_empty, o4_empty, o6_empty, o7_empty, o8_empty, o9_empty,
		i3_status, i4_status, i6_status,
		i3_full, i4_full, i6_full,

		oc0_cfg, oc1_cfg, oc2_cfg, oc3_cfg, oc4_cfg, oc5_cfg,
		ic0_cfg, ic1_cfg, ic2_cfg,

		dma_req, dma_ack);

input		clk, rst;
input	[1:0]	o3_status, o4_status, o6_status, o7_status, o8_status, o9_status;
input		o3_empty, o4_empty, o6_empty, o7_empty, o8_empty, o9_empty;
input	[1:0]	i3_status, i4_status, i6_status;
input		i3_full, i4_full, i6_full;
input	[7:0]	oc0_cfg;
input	[7:0]	oc1_cfg;
input	[7:0]	oc2_cfg;
input	[7:0]	oc3_cfg;
input	[7:0]	oc4_cfg;
input	[7:0]	oc5_cfg;
input	[7:0]	ic0_cfg;
input	[7:0]	ic1_cfg;
input	[7:0]	ic2_cfg;
output	[8:0]	dma_req;
input	[8:0]	dma_ack;

////////////////////////////////////////////////////////////////////
//
// DMA Request Modules
//

ac97_dma_req u0(.clk(		clk		),
		.rst(		rst		),
		.cfg(		oc0_cfg		),
		.status(	o3_status	),
		.full_empty(	o3_empty	),
		.dma_req(	dma_req[0]	),
		.dma_ack(	dma_ack[0]	)
		);

ac97_dma_req u1(.clk(		clk		),
		.rst(		rst		),
		.cfg(		oc1_cfg		),
		.status(	o4_status	),
		.full_empty(	o4_empty	),
		.dma_req(	dma_req[1]	),
		.dma_ack(	dma_ack[1]	)
		);

`ifdef AC97_CENTER
ac97_dma_req u2(.clk(		clk		),
		.rst(		rst		),
		.cfg(		oc2_cfg		),
		.status(	o6_status	),
		.full_empty(	o6_empty	),
		.dma_req(	dma_req[2]	),
		.dma_ack(	dma_ack[2]	)
		);
`else
assign dma_req[2] = 1'b0;
`endif

`ifdef AC97_SURROUND
ac97_dma_req u3(.clk(		clk		),
		.rst(		rst		),
		.cfg(		oc3_cfg		),
		.status(	o7_status	),
		.full_empty(	o7_empty	),
		.dma_req(	dma_req[3]	),
		.dma_ack(	dma_ack[3]	)
		);

ac97_dma_req u4(.clk(		clk		),
		.rst(		rst		),
		.cfg(		oc4_cfg		),
		.status(	o8_status	),
		.full_empty(	o8_empty	),
		.dma_req(	dma_req[4]	),
		.dma_ack(	dma_ack[4]	)
		);
`else
assign dma_req[3] = 1'b0;
assign dma_req[4] = 1'b0;
`endif

`ifdef AC97_LFE
ac97_dma_req u5(.clk(		clk		),
		.rst(		rst		),
		.cfg(		oc5_cfg		),
		.status(	o9_status	),
		.full_empty(	o9_empty	),
		.dma_req(	dma_req[5]	),
		.dma_ack(	dma_ack[5]	)
		);
`else
assign dma_req[5] = 1'b0;
`endif

`ifdef AC97_SIN
ac97_dma_req u6(.clk(		clk		),
		.rst(		rst		),
		.cfg(		ic0_cfg		),
		.status(	i3_status	),
		.full_empty(	i3_full		),
		.dma_req(	dma_req[6]	),
		.dma_ack(	dma_ack[6]	)
		);

ac97_dma_req u7(.clk(		clk		),
		.rst(		rst		),
		.cfg(		ic1_cfg		),
		.status(	i4_status	),
		.full_empty(	i4_full		),
		.dma_req(	dma_req[7]	),
		.dma_ack(	dma_ack[7]	)
		);
`else
assign dma_req[6] = 1'b0;
assign dma_req[7] = 1'b0;
`endif

`ifdef AC97_MICIN
ac97_dma_req u8(.clk(		clk		),
		.rst(		rst		),
		.cfg(		ic2_cfg		),
		.status(	i6_status	),
		.full_empty(	i6_full		),
		.dma_req(	dma_req[8]	),
		.dma_ack(	dma_ack[8]	)
		);
`else
assign dma_req[8] = 1'b0;
`endif

endmodule
module ac97_dma_req(clk, rst, cfg, status, full_empty, dma_req, dma_ack);
input		clk, rst;
input	[7:0]	cfg;
input	[1:0]	status;
input		full_empty;
output		dma_req;
input		dma_ack;

////////////////////////////////////////////////////////////////////
//
// Local Wires
//
reg	dma_req_d;
reg	dma_req_r1;
reg	dma_req;

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

always @(cfg or status or full_empty)
	case(cfg[5:4])	// synopsys parallel_case full_case
			// REQ = Ch_EN & DMA_EN & Status
			// 1/4 full/empty
	   2'h2: dma_req_d = cfg[0] & cfg[6] & (full_empty | (status == 2'h0));
			// 1/2 full/empty
	   2'h1: dma_req_d = cfg[0] & cfg[6] & (full_empty | (status[1] == 1'h0));
			// 3/4 full/empty
	   2'h0: dma_req_d = cfg[0] & cfg[6] & (full_empty | (status < 2'h3));
	   2'h3: dma_req_d = cfg[0] & cfg[6] & full_empty;
	endcase

always @(posedge clk)
	dma_req_r1 <= #1 dma_req_d & !dma_ack;

always @(posedge clk or negedge rst)
	if(!rst)				dma_req <= #1 1'b0;
	else
	if(dma_req_r1 & dma_req_d & !dma_ack) 	dma_req <= #1 1'b1;
	else
	if(dma_ack) 				dma_req <= #1 1'b0;

endmodule