dakies/OSS_Verilog huggingface dataset:
module ram (
    input clk,
    input [63:0] address_in,
    input sel_in,
    output wire [63:0] read_value_out,
    input [7:0] write_mask_in,
    input [63:0] write_value_in
);
    reg [63:0] mem [4095:0];
    reg [63:0] read_value;

    assign read_value_out = sel_in ? read_value : 0;

    always @(negedge clk) begin
        read_value <= {mem[address_in[63:4]][7:0], mem[address_in[63:4]][15:8], mem[address_in[63:4]][23:16], mem[address_in[63:4]][63:24], mem[address_in[63:4]][39:32], mem[address_in[63:4]][47:40], mem[address_in[63:4]][55:48], mem[address_in[63:4]][63:56]};

        if (sel_in) begin
            if (write_mask_in[7])
                mem[address_in[63:4]][7:0] <= write_value_in[63:56]; 

            if (write_mask_in[6])
                mem[address_in[63:4]][15:8] <= write_value_in[55:48]; 

            if (write_mask_in[5])
                mem[address_in[63:4]][23:16] <= write_value_in[47:40]; 

            if (write_mask_in[4])
                mem[address_in[63:4]][31:24] <= write_value_in[39:32]; 

            if (write_mask_in[3])
                mem[address_in[63:4]][39:32] <= write_value_in[31:24]; 

            if (write_mask_in[2])
                mem[address_in[63:4]][47:40] <= write_value_in[23:16]; 

            if (write_mask_in[1])
                mem[address_in[63:4]][55:48] <= write_value_in[15:8];

            if (write_mask_in[0])
                mem[address_in[63:4]][63:56] <= write_value_in[7:0]; 
        end
    end
endmodule
module uart (
    input clk,
    input reset,

    input rx_in,
    output wire tx_out,

    input [63:0] address_in,
    input sel_in,
    input read_in,
    output reg [63:0] read_value_out,
    input [3:0] write_mask_in,
    input [63:0] write_value_in
);
    reg [31:0] clk_div;

    reg [31:0] rx_clks;
    reg [7:0] rx_bits;
    reg [15:0] rx_buf;

    reg [15:0] rx_read_buf;
    reg rx_read_ready;

    reg [31:0] tx_clks;
    reg [7:0] tx_bits;
    reg [19:0] tx_buf;

    wire tx_write_ready;

    initial
        tx_buf[0] = 1;

    assign tx_out = tx_buf[0];
    assign tx_write_ready = ~|tx_bits;

    always @* begin
        if (sel_in) begin
            case (address_in[3:2])
                `UART_REG_CLK_DIV: begin
                    read_value_out = {32'b0, clk_div};
                end
                `UART_REG_STATUS: begin
                    read_value_out = {60'b0, rx_read_ready, tx_write_ready};
                end
                `UART_REG_DATA: begin
                    read_value_out = {{48{~rx_read_ready}}, rx_read_ready ? rx_read_buf : 16'b0};
                end
            endcase
        end else begin
            read_value_out = 0;
        end
    end
    always @(posedge clk) begin
        if (sel_in) begin
            case (address_in[3:2])
                `UART_REG_CLK_DIV: begin
                    if (write_mask_in[1])
                        clk_div[31:16] <= write_value_in[31:16];

                    if (write_mask_in[0])
                        clk_div[15:0] <= write_value_in[15:0];
                end
                `UART_REG_DATA: begin
                    if (read_in)
                        rx_read_ready <= 0;

                    if (write_mask_in[0] && !tx_bits) begin
                        tx_clks <= clk_div;
                        tx_bits <= 20;
                        tx_buf <= {1'b1, write_value_in[15:0], 1'b0};
                    end
                end
            endcase
        end

        if (rx_bits) begin
            if (rx_clks) begin
                rx_clks <= rx_clks - 1;
            end else begin
                rx_clks <= clk_div;
                rx_bits <= rx_bits - 1;

                case (rx_bits)
                    20: begin
                        if (rx_in)
                            rx_bits <= 0;
                    end
                    1: begin
                        if (rx_in) begin
                            rx_read_ready <= 1;
                            rx_read_buf <= rx_buf;
                        end
                    end
                endcase
            end
        end else if (!rx_in) begin
            rx_clks <= clk_div[31:1];
            rx_bits <= 20;
        end

        if (tx_bits) begin
            if (tx_clks) begin
                tx_clks <= tx_clks - 1;
            end else begin
                tx_clks <= clk_div;
                tx_bits <= tx_bits - 1;
                tx_buf <= {1'b1, tx_buf[19:1]};
            end
        end

        if (reset) begin
            rx_bits <= 0;

            tx_bits <= 0;
            tx_buf[0] <= 1;
        end
    end
endmodule
module clk_div #(
    parameter LOG_DIVISOR = 1
) (
    input clk_in,
    output wire clk_out
);
    reg [LOG_DIVISOR-1:0] q;

    always @(posedge clk_in)
        q <= q + 1;

    assign clk_out = q[LOG_DIVISOR-1];
endmodule
module regs (
    input clk,
    input stall_in,

    input [8:0] rs1_in,
    input [8:0] rs2_in,
    input [8:0] rd_in,
    input rd_write_in,

    input [63:0] rd_value_in,

    output reg [63:0] rs1_value_out,
    output reg [63:0] rs2_value_out
);
    reg [63:0] regs [63:0];

    generate
        genvar i;
        for (i = 0; i < 64; i = i+1) begin
            initial
                regs[i] <= 0;
        end
    endgenerate

    always @(posedge clk) begin
        if (!stall_in) begin
            rs1_value_out <= regs[rs1_in];
            rs2_value_out <= regs[rs2_in];
        end

        if (rd_write_in && |rd_in)
            regs[rd_in] <= rd_value_in;
    end
endmodule
module imm_mux (
    input [4:0] imm_in,

    input [63:0] instr_in,

    output reg [63:0] imm_value_out
);
    wire sign;

    wire [63:0] imm_i;
    wire [63:0] imm_s;
    wire [63:0] imm_b;
    wire [63:0] imm_u;
    wire [63:0] imm_j;

    wire [63:0] shamt;
    wire [63:0] zimm;

    assign sign = instr_in[63];

    assign imm_i = {{42{sign}}, instr_in[60:50], instr_in[48:42], instr_in[40]};
    assign imm_s = {{42{sign}}, instr_in[60:50], instr_in[22:16],  instr_in[16]};
    assign imm_b = {{40{sign}}, instr_in[7],     instr_in[60:50], instr_in[22:16],  2'b0};
    assign imm_u = {sign,       instr_in[60:40], instr_in[39:12], 24'b0};
    assign imm_j = {{24{sign}}, instr_in[40:24], instr_in[40],    instr_in[60:50], instr_in[48:47], 2'b0};

    assign shamt = {44'bx, instr_in[48:40]};
    assign zimm  = {44'b0, instr_in[38:30]};

    always @* begin
        case (imm_in)
            `IMM_I:     imm_value_out = imm_i;
            `IMM_S:     imm_value_out = imm_s;
            `IMM_B:     imm_value_out = imm_b;
            `IMM_U:     imm_value_out = imm_u;
            `IMM_J:     imm_value_out = imm_j;
            `IMM_SHAMT: imm_value_out = shamt;
            `IMM_ZIMM:  imm_value_out = zimm;
        endcase
    end
endmodule
module sync #(
    parameter BITS = 1
) (
    input clk,
    input [BITS-1:0] in,
    output reg [BITS-1:0] out
);
    reg [BITS-1:0] metastable;

    always @(posedge clk) begin
        metastable <= in;
        out <= metastable;
    end
endmodule
module bus_arbiter (
    input [63:0] instr_address_in,
    input instr_read_in,
    output reg [63:0] instr_read_value_out,
    output reg instr_ready,
    input [63:0] data_address_in,
    input data_read_in,
    input data_write_in,
    output reg [63:0] data_read_value_out,
    input [7:0] data_write_mask_in,
    input [63:0] data_write_value_in,
    output reg data_ready,
    output reg [63:0] address_out,
    output reg read_out,
    output reg write_out,
    input [63:0] read_value_in,
    output reg [7:0] write_mask_out,
    output reg [63:0] write_value_out
);
    always @* begin
        if (data_read_in || data_write_in) begin
            address_out = data_address_in;
            read_out = data_read_in;
            write_out = data_write_in;
            instr_read_value_out = 64'bx;
            data_read_value_out = read_value_in;
            write_mask_out = data_write_mask_in;
            write_value_out = data_write_value_in;
            instr_ready = 1'b0;
            data_ready = 1'b1;
        end else if (instr_read_in) begin
            address_out = instr_address_in;
            read_out = instr_read_in;
            write_out = 1'b0;
            instr_read_value_out = read_value_in;
            data_read_value_out = 64'bx;
            write_mask_out = 8'b0;
            write_value_out = 64'bx;
            instr_ready = 1'b1;
            data_ready = 1'b0;
        end else begin
            address_out = 64'bx;
            read_out = 1'b0;
            write_out = 1'b0;
            instr_read_value_out = 64'bx;
            data_read_value_out = 64'bx;
            write_mask_out = 8'b0;
            write_value_out = 64'bx;
            instr_ready = 1'b0;
            data_ready = 1'b0;
        end
    end
endmodule
module hazard_unit (
    
    input [8:0] decode_rs1_unreg_in,
    input decode_rs1_read_unreg_in,
    input [8:0] decode_rs2_unreg_in,
    input decode_rs2_read_unreg_in,
    input decode_mem_fence_unreg_in,

    input decode_mem_read_in,
    input decode_mem_fence_in,
    input [8:0] decode_rd_in,
    input decode_rd_write_in,

    input execute_mem_fence_in,

    input mem_branch_mispredicted_in,

    input instr_read_in,
    input instr_ready_in,

    input data_read_in,
    input data_write_in,
    input data_ready_in,

    output wire fetch_stall_out,
    output wire fetch_flush_out,

    output wire decode_stall_out,
    output wire decode_flush_out,

    output wire execute_stall_out,
    output wire execute_flush_out,

    output wire mem_stall_out,
    output wire mem_flush_out
);
    wire rs1_matches;
    wire rs2_matches;
    wire fetch_wait_for_bus;
    wire fetch_wait_for_mem_read;
    wire fetch_wait_for_mem_fence;
    wire mem_wait_for_bus;

    assign rs1_matches = decode_rs1_unreg_in == decode_rd_in && decode_rs1_read_unreg_in;
    assign rs2_matches = decode_rs2_unreg_in == decode_rd_in && decode_rs2_read_unreg_in;
    assign fetch_wait_for_bus = instr_read_in && !instr_ready_in;
    assign fetch_wait_for_mem_read = (rs1_matches || rs2_matches) && |decode_rd_in && decode_mem_read_in && decode_rd_write_in;
    assign fetch_wait_for_mem_fence = decode_mem_fence_unreg_in || decode_mem_fence_in || execute_mem_fence_in;
    assign mem_wait_for_bus = (data_read_in || data_write_in) && !data_ready_in;

    assign fetch_stall_out = decode_stall_out || fetch_wait_for_mem_read || fetch_wait_for_bus;
    assign fetch_flush_out = 0;

    assign decode_stall_out = execute_stall_out;
    assign decode_flush_out = fetch_stall_out || mem_branch_mispredicted_in;

    assign execute_stall_out = mem_stall_out;
    assign execute_flush_out = decode_stall_out || mem_branch_mispredicted_in;

    assign mem_stall_out = mem_wait_for_bus;
    assign mem_flush_out = execute_stall_out;
endmodule
module branch_pc_mux (

    input pc_src_in,

    input [63:0] pc_in,
    input [63:0] rs1_value_in,
    input [63:0] imm_value_in,

    output wire [63:0] pc_out 
);
    wire [63:0] pc;

    assign pc = (pc_src_in ? rs1_value_in : pc_in) + imm_value_in;
    assign pc_out = {pc[63:1], 2'b00};
endmodule
module branch_unit (

    input predicted_taken_in,
    input alu_non_zero_in,
    input [2:0] op_in,

    output wire mispredicted_out
);
    reg taken;

    always @* begin
        case (op_in)
            `BRANCH_OP_NEVER:    taken = 0;
            `BRANCH_OP_ZERO:     taken = ~alu_non_zero_in;
            `BRANCH_OP_NON_ZERO: taken = alu_non_zero_in;
            `BRANCH_OP_ALWAYS:   taken = 1;
        endcase
    end

    assign mispredicted_out = taken != predicted_taken_in;
endmodule
module alu (
    
    input [4:0] op_in,
    input sub_sra_in,
    input [2:0] src1_in,
    input [2:0] src2_in,

    input [63:0] pc_in,
    input [63:0] rs1_value_in,
    input [63:0] rs2_value_in,
    input [63:0] imm_value_in,

    output wire non_zero_out,

    output reg [63:0] result_out
);
    reg [63:0] src1;
    reg [63:0] src2;

    wire src1_sign;
    wire src2_sign;

    wire [8:0] shamt;

    wire [64:0] add_sub;
    wire [63:0] srl_sra;

    wire carry;
    wire sign;
    wire ovf;

    wire lt;
    wire ltu;

    always @* begin
        case (src1_in)
            `ALU_SRC1_REG:  src1 = rs1_value_in;
            `ALU_SRC1_PC:   src1 = pc_in;
            `ALU_SRC1_ZERO: src1 = 0;
        endcase

        case (src2_in)
            `ALU_SRC2_REG:  src2 = rs2_value_in;
            `ALU_SRC2_IMM:  src2 = imm_value_in;
            `ALU_SRC2_FOUR: src2 = 8;
        endcase
    end

    assign src1_sign = src1[63];
    assign src2_sign = src2[63];

    assign shamt = src2[8:0];

    assign add_sub = sub_sra_in ? src1 - src2 : src1 + src2;
    assign srl_sra = $signed({sub_sra_in ? src1_sign : 2'b0, src1}) >>> shamt;

    assign carry = add_sub[64];
    assign sign  = add_sub[63];
    assign ovf   = (!src1_sign && src2_sign && sign) || (src1_sign && !src2_sign && !sign);

    assign lt  = sign != ovf;
    assign ltu = carry;

    always @* begin
        case (op_in)
            `ALU_OP_ADD_SUB: result_out = add_sub[63:0];
            `ALU_OP_XOR:     result_out = src1 ^ src2;
            `ALU_OP_OR:      result_out = src1 | src2;
            `ALU_OP_AND:     result_out = src1 & src2;
            `ALU_OP_SLL:     result_out = src1 << shamt;
            `ALU_OP_SRL_SRA: result_out = srl_sra;
            `ALU_OP_SLT:     result_out = {63'b0, lt};
            `ALU_OP_SLTU:    result_out = {63'b0, ltu};
        endcase
    end

    assign non_zero_out = |result_out;
endmodule
module  pll_audio_0002(

	// interface 'refclk'
	input wire refclk,

	// interface 'reset'
	input wire rst,

	// interface 'outclk0'
	output wire outclk_0,

	// interface 'locked'
	output wire locked
);

	altera_pll #(
		.fractional_vco_multiplier("true"),
		.reference_clock_frequency("50.0 MHz"),
		.operation_mode("direct"),
		.number_of_clocks(1),
		.output_clock_frequency0("24.576000 MHz"),
		.phase_shift0("0 ps"),
		.duty_cycle0(50),
		.pll_type("General"),
		.pll_subtype("General")
	) altera_pll_i (
		.rst	(rst),
		.outclk	({outclk_0}),
		.locked	(locked),
		.fboutclk	( ),
		.fbclk	(1'b0),
		.refclk	(refclk)
	);
endmodule
module hps_interface
(
    // HPS interface
    input      [15:0]  gp_in,
    output reg [31:0]  gp_out,
    output reg         io_strobe,

    // HPS SPI
    input  spi_mosi,
    output spi_miso,
    input  spi_clk,
    input  spi_cs,

    // other HPS signals
    input fpga_enable,
    input osd_enable,
    input io_enable,

    input  sync_clk,
    input  sys_clk,
    input  reset
);

wire [15:0] gp_word_out;
wire        spi_rx_strobe;

reg  cs,      _cs;
reg  mosi,    _mosi;
reg  sck,     _sck;
reg  fpga_en, _fpga_en;
reg  osd_en,  _osd_en;
reg  io_en,   _io_en;

always @(posedge sync_clk) begin
    if (reset) begin
        cs <= 0;      _cs <= 0;
        mosi <= 0;    _mosi <= 0;
        sck <= 0;     _sck <= 0;
        fpga_en <= 0; _fpga_en <= 0;
        osd_en <= 0;  _osd_en <= 0;
        io_en <= 0;   _io_en <= 0;
    end else begin
        cs      <= _cs;      _cs      <= spi_cs;
        mosi    <= _mosi;    _mosi    <= spi_mosi;
        sck     <= _sck;     _sck     <= spi_clk;
        fpga_en <= _fpga_en; _fpga_en <= fpga_enable;
        osd_en  <= _osd_en;  _osd_en  <= osd_enable;
        io_en   <= _io_en;   _io_en   <= io_enable;
    end
end

spi_slave spi_slave (
    .spi_device__sck(sck),
    .spi_device__sdo(spi_miso),
    .spi_device__sdi(mosi),
    .spi_device__cs(cs),
    .word_in(gp_word_out),
    .word_out(gp_in),
    .word_complete(spi_rx_strobe),
    .clk(sys_clk),
    .rst(reset)
);

always @(posedge sys_clk) begin
    if (reset) begin
        gp_out    <= 0;
        io_strobe <= 0;
    end else begin
        gp_out <= {
            11'b0,          // [31:21]
            io_en,          // [20]
            osd_en,         // [19]
            fpga_en,        // [18]
            2'b0,           // [17:16]
            gp_word_out     // [15:0]
        };
        io_strobe <= spi_rx_strobe;
    end
end

endmodule
module pll_audio (
		input  wire  refclk,   //  refclk.clk
		input  wire  rst,      //   reset.reset
		output wire  outclk_0  // outclk0.clk
	);

	pll_audio_0002 pll_audio_inst (
		.refclk   (refclk),   //  refclk.clk
		.rst      (rst),      //   reset.reset
		.outclk_0 (outclk_0), // outclk0.clk
		.locked   ()          // (terminated)
	);

endmodule
module sigma_delta_dac #(parameter MSBI=7, parameter INV=1'b1)
(
   output reg      DACout, //Average Output feeding analog lowpass
   input  [MSBI:0] DACin,  //DAC input (excess 2**MSBI)
   input           CLK,
   input           RESET
);

reg [MSBI+2:0] DeltaAdder; //Output of Delta Adder
reg [MSBI+2:0] SigmaAdder; //Output of Sigma Adder
reg [MSBI+2:0] SigmaLatch; //Latches output of Sigma Adder
reg [MSBI+2:0] DeltaB;     //B input of Delta Adder

always @(*) DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1);
always @(*) DeltaAdder = DACin + DeltaB;
always @(*) SigmaAdder = DeltaAdder + SigmaLatch;

always @(posedge CLK or posedge RESET) begin
   if(RESET) begin
      SigmaLatch <= 1'b1 << (MSBI+1);
      DACout <= INV;
   end else begin
      SigmaLatch <= SigmaAdder;
      DACout <= SigmaLatch[MSBI+2] ^ INV;
   end
end

endmodule
module IIR_filter
#(
	parameter use_params = 1,                     // set to 1 to use following parameters, 0 for input port variables.
	parameter stereo   =  1,                      // 0 for mono (input_l)

	parameter coeff_x  =  0.00000774701983513660, // Base gain value for X. Float. Range: 0.0 ... 0.999(9)
	parameter coeff_x0 =  3,                      // Gain scale factor for X0. Integer. Range -7 ... +7
	parameter coeff_x1 =  3,                      // Gain scale factor for X1. Integer. Range -7 ... +7
	parameter coeff_x2 =  1,                      // Gain scale factor for X2. Integer. Range -7 ... +7
	parameter coeff_y0 = -2.96438150626551080000, // Coefficient for Y0. Float. Range -3.999(9) ... 3.999(9)
	parameter coeff_y1 =  2.92939452735121100000, // Coefficient for Y1. Float. Range -3.999(9) ... 3.999(9)
	parameter coeff_y2 = -0.96500747158831091000  // Coefficient for Y2. Float. Range -3.999(9) ... 3.999(9)
)
(
	input         clk,
	input         reset,

	input         ce,        // must be double of calculated rate for stereo!
	input         sample_ce, // desired output sample rate

	input  [39:0] cx,
	input   [7:0] cx0,
	input   [7:0] cx1,
	input   [7:0] cx2,
	input  [23:0] cy0,
	input  [23:0] cy1,
	input  [23:0] cy2,

	input  [15:0] input_l,  input_r,  // signed samples
	output [15:0] output_l, output_r  // signed samples
);

localparam  [39:0] pcoeff_x  = coeff_x  * 40'h8000000000;
localparam  [31:0] pcoeff_y0 = coeff_y0 * 24'h200000;
localparam  [31:0] pcoeff_y1 = coeff_y1 * 24'h200000;
localparam  [31:0] pcoeff_y2 = coeff_y2 * 24'h200000;

wire [39:0] vcoeff    = use_params ? pcoeff_x        : cx;
wire [23:0] vcoeff_y0 = use_params ? pcoeff_y0[23:0] : cy0;
wire [23:0] vcoeff_y1 = use_params ? pcoeff_y1[23:0] : cy1;
wire [23:0] vcoeff_y2 = use_params ? pcoeff_y2[23:0] : cy2;

wire [59:0] inp_mul = $signed(inp) * $signed(vcoeff);

wire [39:0] x = inp_mul[59:20];
wire [39:0] y = x + tap0;

wire [39:0] tap0;
iir_filter_tap iir_tap_0
(
	.clk(clk),
	.reset(reset),
	.ce(ce),
	.ch(ch),
	.cx(use_params ? coeff_x0[7:0] : cx0),
	.cy(vcoeff_y0),
	.x(x),
	.y(y),
	.z(tap1),
	.tap(tap0)
);

wire [39:0] tap1;
iir_filter_tap iir_tap_1
(
	.clk(clk),
	.reset(reset),
	.ce(ce),
	.ch(ch),
	.cx(use_params ? coeff_x1[7:0] : cx1),
	.cy(vcoeff_y1),
	.x(x),
	.y(y),
	.z(tap2),
	.tap(tap1)
);

wire [39:0] tap2;
iir_filter_tap iir_tap_2
(
	.clk(clk),
	.reset(reset),
	.ce(ce),
	.ch(ch),
	.cx(use_params ? coeff_x2[7:0] : cx2),
	.cy(vcoeff_y2),
	.x(x),
	.y(y),
	.z(0),
	.tap(tap2)
);

wire [15:0] y_clamp = (~y[39] & |y[38:35]) ? 16'h7FFF : (y[39] & ~&y[38:35]) ? 16'h8000 : y[35:20];

reg        ch = 0;
reg [15:0] out_l, out_r, out_m;
reg [15:0] inp, inp_m;
always @(posedge clk) if (ce) begin
	if(!stereo) begin
		ch    <= 0;
		inp   <= input_l;
		out_l <= y_clamp;
		out_r <= y_clamp;
	end
	else begin
		ch <= ~ch;
		if(ch) begin
			out_m <= y_clamp;
			inp   <= inp_m;
		end
		else begin
			out_l <= out_m;
			out_r <= y_clamp;
			inp   <= input_l;
			inp_m <= input_r;
		end
	end
end

reg [31:0] out;
always @(posedge clk) if (sample_ce) out <= {out_l, out_r};

assign {output_l, output_r} = out;

endmodule
module iir_filter_tap
(
	input         clk,
	input         reset,

	input         ce,
	input         ch,

	input   [7:0] cx,
	input  [23:0] cy,

	input  [39:0] x,
	input  [39:0] y,
	input  [39:0] z,
	output [39:0] tap
);

wire signed [60:0] y_mul = $signed(y[36:0]) * $signed(cy);

function [39:0] x_mul;
	input [39:0] x;
begin
	x_mul = 0;
	if(cx[0]) x_mul =  x_mul + {{4{x[39]}}, x[39:4]};
	if(cx[1]) x_mul =  x_mul + {{3{x[39]}}, x[39:3]};
	if(cx[2]) x_mul =  x_mul + {{2{x[39]}}, x[39:2]};
	if(cx[7]) x_mul = ~x_mul; //cheap NEG
end
endfunction

(* ramstyle = "logic" *) reg [39:0] intreg[2];
always @(posedge clk, posedge reset) begin
	if(reset) {intreg[0],intreg[1]} <= 80'd0;
	else if(ce) intreg[ch] <= x_mul(x) - y_mul[60:21] + z;
end

assign tap = intreg[ch];

endmodule
module DC_blocker
(
	input         clk,
	input         ce, // 48/96 KHz
	input         mute,

	input         sample_rate,
	input  [15:0] din,
	output [15:0] dout
);

wire [39:0] x  = {din[15], din, 23'd0};
wire [39:0] x0 = x - (sample_rate ? {{11{x[39]}}, x[39:11]} : {{10{x[39]}}, x[39:10]});
wire [39:0] y1 = y - (sample_rate ? {{10{y[39]}}, y[39:10]} : {{09{y[39]}}, y[39:09]});
wire [39:0] y0 = x0 - x1 + y1;

reg  [39:0] x1, y;
always @(posedge clk) if(ce) begin
	x1 <= x0;
	y  <= ^y0[39:38] ? {{2{y0[39]}},{38{y0[38]}}} : y0;
end

assign dout = mute ? 16'd0 : y[38:23];

endmodule
module pll_hdmi (
		input  wire        refclk,            //            refclk.clk
		input  wire        rst,               //             reset.reset
		output wire        outclk_0,          //           outclk0.clk
		input  wire [63:0] reconfig_to_pll,   //   reconfig_to_pll.reconfig_to_pll
		output wire [63:0] reconfig_from_pll  // reconfig_from_pll.reconfig_from_pll
	);

	pll_hdmi_0002 pll_hdmi_inst (
		.refclk            (refclk),            //            refclk.clk
		.rst               (rst),               //             reset.reset
		.outclk_0          (outclk_0),          //           outclk0.clk
		.reconfig_to_pll   (reconfig_to_pll),   //   reconfig_to_pll.reconfig_to_pll
		.reconfig_from_pll (reconfig_from_pll), // reconfig_from_pll.reconfig_from_pll
		.locked            ()                   //       (terminated)
	);

endmodule
module pll_cfg #(
		parameter ENABLE_BYTEENABLE   = 0,
		parameter BYTEENABLE_WIDTH    = 4,
		parameter RECONFIG_ADDR_WIDTH = 6,
		parameter RECONFIG_DATA_WIDTH = 32,
		parameter reconf_width        = 64,
		parameter WAIT_FOR_LOCK       = 1
	) (
		input  wire        mgmt_clk,          //          mgmt_clk.clk
		input  wire        mgmt_reset,        //        mgmt_reset.reset
		output wire        mgmt_waitrequest,  // mgmt_avalon_slave.waitrequest
		input  wire        mgmt_read,         //                  .read
		input  wire        mgmt_write,        //                  .write
		output wire [31:0] mgmt_readdata,     //                  .readdata
		input  wire [5:0]  mgmt_address,      //                  .address
		input  wire [31:0] mgmt_writedata,    //                  .writedata
		output wire [63:0] reconfig_to_pll,   //   reconfig_to_pll.reconfig_to_pll
		input  wire [63:0] reconfig_from_pll  // reconfig_from_pll.reconfig_from_pll
	);

	altera_pll_reconfig_top #(
		.device_family       ("Cyclone V"),
		.ENABLE_MIF          (0),
		.MIF_FILE_NAME       ("sys/pll_cfg.mif"),
		.ENABLE_BYTEENABLE   (ENABLE_BYTEENABLE),
		.BYTEENABLE_WIDTH    (BYTEENABLE_WIDTH),
		.RECONFIG_ADDR_WIDTH (RECONFIG_ADDR_WIDTH),
		.RECONFIG_DATA_WIDTH (RECONFIG_DATA_WIDTH),
		.reconf_width        (reconf_width),
		.WAIT_FOR_LOCK       (WAIT_FOR_LOCK)
	) pll_cfg_inst (
		.mgmt_clk          (mgmt_clk),          //          mgmt_clk.clk
		.mgmt_reset        (mgmt_reset),        //        mgmt_reset.reset
		.mgmt_waitrequest  (mgmt_waitrequest),  // mgmt_avalon_slave.waitrequest
		.mgmt_read         (mgmt_read),         //                  .read
		.mgmt_write        (mgmt_write),        //                  .write
		.mgmt_readdata     (mgmt_readdata),     //                  .readdata
		.mgmt_address      (mgmt_address),      //                  .address
		.mgmt_writedata    (mgmt_writedata),    //                  .writedata
		.reconfig_to_pll   (reconfig_to_pll),   //   reconfig_to_pll.reconfig_to_pll
		.reconfig_from_pll (reconfig_from_pll), // reconfig_from_pll.reconfig_from_pll
		.mgmt_byteenable   (4'b0000)            //       (terminated)
	);

endmodule
module DPR2KV
(
	input					CL0,
	input	[10:0]		AD0,
	input					EN0,
	input					WR0,
	input  [7:0]		DI0,
	output [7:0]		DO0,
	
	input					CL1,
	input	[10:0]		AD1,
	output [7:0]		DO1
);

DPR2K ram(
	CL0, AD0,  EN0,  WR0,  DI0, DO0,
	CL1, AD1, 1'b1, 1'b0, 8'h0, DO1
);

endmodule
module DPR2K
(
	input					CL0,
	input	[10:0]		AD0,
	input					EN0,
	input					WR0,
	input  [7:0]		DI0,
	output reg [7:0]	DO0,
	
	input					CL1,
	input	[10:0]		AD1,
	input					EN1,
	input					WR1,
	input  [7:0]		DI1,
	output reg [7:0]	DO1
);

reg [7:0] core[0:2047] /* synthesis ramstyle = "no_rw_check, M10K" */;

always @( posedge CL0 ) begin
	if (EN0) begin
		DO0 <= core[AD0];
		if (WR0) core[AD0] <= DI0;
	end
end

always @( posedge CL1 ) begin
	if (EN1) begin
		DO1 <= core[AD1];
		if (WR1) core[AD1] <= DI1;
	end
end

endmodule
module LBUF1K
(
	input				CL0,
	input	 [9:0]	AD0,
	input				WR0,
	input  [7:0]	DI0,
	
	input				CL1,
	input	 [9:0]	AD1,
	input				WR1,
	input  [7:0]	DI1,
	output [7:0]	DO1
);

dpram #(10,8) lbuf(
	.clock_a(CL0),
	.address_a(AD0),
	.data_a(DI0),
	.wren_a(WR0),
	.q_a(),

	.clock_b(CL1),
	.address_b(AD1),
	.data_b(DI1),
	.wren_b(WR1),
	.q_b(DO1)
);

endmodule
module DLROM #(parameter AW=8,parameter DW=8)
(
	input							CL0,
	input [(AW-1):0]			AD0,
	output reg [(DW-1):0]	DO0,

	input							CL1,
	input [(AW-1):0]			AD1,
	input	[(DW-1):0]			DI1,
	input							WE1
);

reg [DW-1:0] core[0:((2**AW)-1)] /* synthesis ramstyle = "no_rw_check, M10K" */;

always @(posedge CL0) DO0 <= core[AD0];
always @(posedge CL1) if (WE1) core[AD1] <= DI1;

endmodule
module DLROMe #(parameter AW=8,parameter DW=8)
(
	input							RE0,
	input							CL0,
	input [(AW-1):0]			AD0,
	output reg [(DW-1):0]	DO0,

	input							CL1,
	input [(AW-1):0]			AD1,
	input	[(DW-1):0]			DI1,
	input							WE1
);

reg [DW-1:0] core[0:((2**AW)-1)] /* synthesis ramstyle = "no_rw_check, M10K" */;

always @(posedge CL0) if (RE0) DO0 <= core[AD0];
always @(posedge CL1) if (WE1) core[AD1] <= DI1;

endmodule
module  pll_0002(

	// interface 'refclk'
	input wire refclk,

	// interface 'reset'
	input wire rst,

	// interface 'outclk0'
	output wire outclk_0,

	// interface 'outclk1'
	output wire outclk_1,

	// interface 'locked'
	output wire locked
);

`ifdef CYCLONEV
	altera_pll #(
		.fractional_vco_multiplier("false"),
		.reference_clock_frequency("50.0 MHz"),
		.operation_mode("direct"),
		.number_of_clocks(2),
		.output_clock_frequency0("49.147727 MHz"),
		.phase_shift0("0 ps"),
		.duty_cycle0(50),
		.output_clock_frequency1("24.573863 MHz"),
		.phase_shift1("0 ps"),
		.duty_cycle1(50),
		.output_clock_frequency2("0 MHz"),
		.phase_shift2("0 ps"),
		.duty_cycle2(50),
		.output_clock_frequency3("0 MHz"),
		.phase_shift3("0 ps"),
		.duty_cycle3(50),
		.output_clock_frequency4("0 MHz"),
		.phase_shift4("0 ps"),
		.duty_cycle4(50),
		.output_clock_frequency5("0 MHz"),
		.phase_shift5("0 ps"),
		.duty_cycle5(50),
		.output_clock_frequency6("0 MHz"),
		.phase_shift6("0 ps"),
		.duty_cycle6(50),
		.output_clock_frequency7("0 MHz"),
		.phase_shift7("0 ps"),
		.duty_cycle7(50),
		.output_clock_frequency8("0 MHz"),
		.phase_shift8("0 ps"),
		.duty_cycle8(50),
		.output_clock_frequency9("0 MHz"),
		.phase_shift9("0 ps"),
		.duty_cycle9(50),
		.output_clock_frequency10("0 MHz"),
		.phase_shift10("0 ps"),
		.duty_cycle10(50),
		.output_clock_frequency11("0 MHz"),
		.phase_shift11("0 ps"),
		.duty_cycle11(50),
		.output_clock_frequency12("0 MHz"),
		.phase_shift12("0 ps"),
		.duty_cycle12(50),
		.output_clock_frequency13("0 MHz"),
		.phase_shift13("0 ps"),
		.duty_cycle13(50),
		.output_clock_frequency14("0 MHz"),
		.phase_shift14("0 ps"),
		.duty_cycle14(50),
		.output_clock_frequency15("0 MHz"),
		.phase_shift15("0 ps"),
		.duty_cycle15(50),
		.output_clock_frequency16("0 MHz"),
		.phase_shift16("0 ps"),
		.duty_cycle16(50),
		.output_clock_frequency17("0 MHz"),
		.phase_shift17("0 ps"),
		.duty_cycle17(50),
		.pll_type("General"),
		.pll_subtype("General")
	) altera_pll_i (
		.rst	(rst),
		.outclk	({outclk_1, outclk_0}),
		.locked	(locked),
		.fboutclk	( ),
		.fbclk	(1'b0),
		.refclk	(refclk)
	);
`else
	ALTPLL #(
		.BANDWIDTH_TYPE("AUTO"),
		.CLK0_DIVIDE_BY(10'd117),
		.CLK0_DUTY_CYCLE(6'd50),
		.CLK0_MULTIPLY_BY(10'd115), // 49.147727 MHz = 50MHz * 115 / 117
		.CLK0_PHASE_SHIFT(1'd0),
		.CLK1_DIVIDE_BY(10'd234),
		.CLK1_DUTY_CYCLE(6'd50),
		.CLK1_MULTIPLY_BY(10'd115), // 24.573863 MHz = 50MHz * 115 / 234
		.CLK1_PHASE_SHIFT(1'd0),
		.COMPENSATE_CLOCK("CLK0"),
		.INCLK0_INPUT_FREQUENCY(15'd20000),
		.OPERATION_MODE("NORMAL")
	) altera_pll_i (
		.ARESET(1'd0),
		.CLKENA(5'd31),
		.EXTCLKENA(4'd15),
		.FBIN(1'd1),
		.INCLK(refclk),
		.PFDENA(1'd1),
		.PLLENA(1'd1),
		.CLK({outclk_1, outclk_0}),
		.LOCKED(locked)
	);
`endif	
endmodule
module pause #(
	parameter						RW=8,						// Width of red channel
	parameter						GW=8,						// Width of green channel
	parameter						BW=8,						// Width of blue channel
	parameter						CLKSPD = 12				// Main clock speed in MHz
)
(
	input								clk_sys,					// Core system clock (should match HPS module)
	input								reset,					// CPU reset signal (active-high)
	input								user_button,			// User pause button signal (active-high)
	input								pause_request,			// Pause requested by other code (active-high)
	input [1:0]						options,					// Pause options from OSD 
																	//   [0] = pause in OSD (active-high)
																	//   [1] = dim video (active-high)
	input 							OSD_STATUS,				// OSD is open (active-high)
	input	[(RW-1):0]				r,							// Red channel
	input	[(GW-1):0]				g,							// Green channel
	input	[(BW-1):0]				b,							// Blue channel

	output							pause_cpu,				// Pause signal to CPU (active-high)
`ifdef PAUSE_OUTPUT_DIM
	output							dim_video,				// Dim video requested (active-high)
`endif
	output [(RW+GW+BW-1):0]		rgb_out					// RGB output to arcade_video module

);

// Option constants
localparam 		pause_in_osd	= 1'b0;
localparam 		dim_video_timer= 1'b1;

reg				pause_toggle	= 1'b0;					// User paused (active-high)
reg [31:0]		pause_timer		= 1'b0;					// Time since pause
reg [31:0]		dim_timeout		= (CLKSPD*10000000);	// Time until video output dim (10 seconds @ CLKSPD Mhz)
`ifndef PAUSE_OUTPUT_DIM
wire 			dim_video;				 				// Dim video requested (active-high)
`endif

assign pause_cpu = (pause_request | pause_toggle  | (OSD_STATUS & options[pause_in_osd])) & !reset;
assign dim_video = (pause_timer >= dim_timeout);

always @(posedge clk_sys) begin : pause_block

	// Track user pause button down
	reg user_button_last;
	user_button_last <= user_button;
	if(!user_button_last & user_button) pause_toggle <= ~pause_toggle;

	// Clear user pause on reset
	if(pause_toggle & reset) pause_toggle <= 0;

	if(pause_cpu & options[dim_video_timer])
	begin
		// Track pause duration for video dim
		if((pause_timer<dim_timeout))
		begin
			pause_timer <= pause_timer + 1'b1;
		end
	end
	else
	begin
		pause_timer <= 1'b0;
	end
end

assign rgb_out = dim_video ? {r >> 1,g >> 1, b >> 1} : {r,g,b};

endmodule
module  pll_0002(
	input wire refclk,
	input wire rst,
	output wire outclk_0,
	output wire outclk_1,
	output wire locked
);

	wire feedback;

	wire outclk_0_bufg;
	wire outclk_1_bufg;
	
	PLLE2_ADV #(
		.CLKFBOUT_MULT(6'd26),
		.CLKIN1_PERIOD(20.0),
		.CLKOUT0_DIVIDE(7'd27), // 48.648 MHz ~= 50 MHz * 26 / 27
		.CLKOUT0_PHASE(1'd0),
		.CLKOUT1_DIVIDE(7'd54), // 24.324 MHz ~= 50 MHz * 26 / 54
		.CLKOUT1_PHASE(1'd0),
		.DIVCLK_DIVIDE(1'd1),
		.REF_JITTER1(0.01),
		.STARTUP_WAIT("FALSE")
	) PLLE2_ADV (
		.CLKFBIN(feedback),
		.CLKIN1(refclk),
		.PWRDWN(1'b0),
		.RST(rst),
		.CLKFBOUT(feedback),
		.CLKOUT0(outclk_0_bufg),
		.CLKOUT1(outclk_1_bufg),
		.LOCKED(locked)
	);

	BUFG outclk_bufg_0 (.I(outclk_0_bufg), .O(outclk_0));
	BUFG outclk_bufg_1 (.I(outclk_1_bufg), .O(outclk_1));	
endmodule
module  pll_0002(
	input wire refclk,
	input wire rst,
	output wire outclk_0,
	output wire outclk_1,
	output wire outclk_2,
	output wire outclk_3,
	output wire locked
);
`ifdef CYCLONEV
	altera_pll #(
		.fractional_vco_multiplier("false"),
		.reference_clock_frequency("50.0 MHz"),
		.operation_mode("direct"),
		.number_of_clocks(4),
		.output_clock_frequency0("50.000000 MHz"),
		.phase_shift0("0 ps"),
		.duty_cycle0(50),
		.output_clock_frequency1("40.000000 MHz"),
		.phase_shift1("0 ps"),
		.duty_cycle1(50),
		.output_clock_frequency2("25.000000 MHz"),
		.phase_shift2("0 ps"),
		.duty_cycle2(50),
		.output_clock_frequency3("100.000000 MHz"),
		.phase_shift3("0 ps"),
		.duty_cycle3(50),
		.pll_type("General"),
		.pll_subtype("General")
	) altera_pll_i (
		.rst	(rst),
		.outclk	({outclk_3, outclk_2, outclk_1, outclk_0}),
		.locked	(locked),
		.fboutclk	( ),
		.fbclk	(1'b0),
		.refclk	(refclk)
	);
`else
	ALTPLL #(
		.BANDWIDTH_TYPE("AUTO"),
		.CLK0_DIVIDE_BY(10'd30),   // 50 MHz
		.CLK0_DUTY_CYCLE(6'd50),
		.CLK0_MULTIPLY_BY(10'd30),
		.CLK0_PHASE_SHIFT(1'd0),
		.CLK1_DIVIDE_BY(10'd24),   // 40 MHz = 50 MHz * 30 / 24
		.CLK1_DUTY_CYCLE(6'd50),
		.CLK1_MULTIPLY_BY(10'd30),
		.CLK1_PHASE_SHIFT(1'd0),
		.CLK2_DIVIDE_BY(10'd60),   // 25 MHz = 50 MHz * 30 / 60
		.CLK2_DUTY_CYCLE(6'd50),
		.CLK2_MULTIPLY_BY(10'd30),
		.CLK2_PHASE_SHIFT(1'd0),
		.CLK3_DIVIDE_BY(10'd15),   // 100 MHz = 50 MHz * 30 / 15
		.CLK3_DUTY_CYCLE(6'd50),
		.CLK3_MULTIPLY_BY(10'd30),
		.CLK3_PHASE_SHIFT(1'd0),
		.COMPENSATE_CLOCK("CLK0"),
		.INCLK0_INPUT_FREQUENCY(15'd20000),
		.OPERATION_MODE("NORMAL")
	) ALTPLL (
		.ARESET(1'd0),
		.CLKENA(5'd31),
		.EXTCLKENA(4'd15),
		.FBIN(1'd1),
		.INCLK(refclk),
		.PFDENA(1'd1),
		.PLLENA(1'd1),
		.CLK({outclk_3, outclk_2, outclk_1, outclk_0}),
		.LOCKED(locked)
	);
`endif
endmodule
module  pll_0002(
	input wire refclk,
	input wire rst,
	output wire outclk_0,
	output wire outclk_1,
	output wire outclk_2,
	output wire outclk_3,
	output wire locked
);

	wire feedback;

	wire outclk_0_bufg;
	wire outclk_1_bufg;
	wire outclk_2_bufg;
	wire outclk_3_bufg;
	
	PLLE2_ADV #(
		.CLKFBOUT_MULT(6'd32),
		.CLKIN1_PERIOD(20.0),
		.CLKOUT0_DIVIDE(7'd32), // 50 MHz = 50 MHz * 32 / 32
		.CLKOUT0_PHASE(1'd0),
		.CLKOUT1_DIVIDE(7'd40), // 40 MHz = 50 MHz * 32 / 40
		.CLKOUT1_PHASE(1'd0),
		.CLKOUT2_DIVIDE(7'd64), // 25 MHz = 50 MHz * 32 / 64
		.CLKOUT2_PHASE(1'd0),
		.CLKOUT3_DIVIDE(7'd16), // 100 MHz = 50 MHz * 32 / 16
		.CLKOUT3_PHASE(1'd0),
		.DIVCLK_DIVIDE(1'd1),
		.REF_JITTER1(0.01),
		.STARTUP_WAIT("FALSE")
	) PLLE2_ADV (
		.CLKFBIN(feedback),
		.CLKIN1(refclk),
		.PWRDWN(1'b0),
		.RST(rst),
		.CLKFBOUT(feedback),
		.CLKOUT0(outclk_0_bufg),
		.CLKOUT1(outclk_1_bufg),
		.CLKOUT2(outclk_2_bufg),
		.CLKOUT3(outclk_3_bufg),
		.LOCKED(locked)
	);

	BUFG outclk_bufg_0 (.I(outclk_0_bufg), .O(outclk_0));
	BUFG outclk_bufg_1 (.I(outclk_1_bufg), .O(outclk_1));
	BUFG outclk_bufg_2 (.I(outclk_2_bufg), .O(outclk_2));
	BUFG outclk_bufg_3 (.I(outclk_3_bufg), .O(outclk_3));
	
endmodule
module  pll_0002(
	input wire refclk,
	input wire rst,
	output wire outclk_0,
	output wire outclk_1,
	output wire locked,
	input wire [63:0] reconfig_to_pll,
	output wire [63:0] reconfig_from_pll
);

	wire feedback;

	wire outclk_0_bufg;
	wire outclk_1_bufg;
	
	PLLE2_ADV #(
		.CLKFBOUT_MULT(6'd30),
		.CLKIN1_PERIOD(20.0),
		.CLKOUT0_DIVIDE(7'd58), // 96.671316 MHz ~= 50 MHz * 30 / 58
		.CLKOUT0_PHASE(1'd0),
		.CLKOUT1_DIVIDE(7'd116), // 48.335658 MHz ~= ~= 50 MHz * 30 / 116
		.CLKOUT1_PHASE(1'd0),
		.DIVCLK_DIVIDE(1'd1),
		.REF_JITTER1(0.01),
		.STARTUP_WAIT("FALSE")
	) PLLE2_ADV (
		.CLKFBIN(feedback),
		.CLKIN1(refclk),
		.PWRDWN(1'b0),
		.RST(rst),
		.CLKFBOUT(feedback),
		.CLKOUT0(outclk_0_bufg),
		.CLKOUT1(outclk_1_bufg),
		.LOCKED(locked)
	);

	BUFG outclk_bufg_0 (.I(outclk_0_bufg), .O(outclk_0));
	BUFG outclk_bufg_1 (.I(outclk_1_bufg), .O(outclk_1));	
endmodule
module irq_sync(
	input CLK,
	input WR_ACK,
	input [2:0] ACK_BITS,
	input RESET_IRQ,
	input TIMER_IRQ,
	input TIMER_IRQ_EN,
	input VBL_IRQ,
	input VBL_IRQ_EN,
	input CLK_EN,
	output IPL0, IPL1
);

	wire [2:0] ACK;
	//wire [3:0] B32_Q;
	
	wire nWR_ACK = ~WR_ACK;

	assign ACK[0] = ~&{nWR_ACK, ACK_BITS[0]};
	assign ACK[1] = ~&{nWR_ACK, ACK_BITS[1]};
	assign ACK[2] = ~&{nWR_ACK, ACK_BITS[2]};
	
	wire B56_Q, B56_nQ, B52_Q, B52_nQ, C52_Q;

	assign B56_nQ = ~B56_Q;
	assign B52_nQ = ~B52_Q;

	//FD3 B56(RESET_IRQ, 1'b0, ACK[0], B56_Q, B56_nQ);
	//FD3 B52(TIMER_IRQ, 1'b0, ACK[1], B52_Q, B52_nQ);
	//FD3 C52(VBL_IRQ, 1'b0, ACK[2], C52_Q);
	register B56(CLK, ~ACK[0], 1'b0, RESET_IRQ, 1'b0, B56_Q);
	register B52(CLK, ~ACK[1], 1'b0, TIMER_IRQ, ~TIMER_IRQ_EN, B52_Q);
	register C52(CLK, ~ACK[2], 1'b0, VBL_IRQ, ~VBL_IRQ_EN, C52_Q);
	
	// B49
	wire B49_OUT = B52_Q | B56_nQ;
	
	// B50A
	wire B50A_OUT = ~|{C52_Q, B56_nQ, B52_nQ};
	
	//FDSCell B32(CLK, {1'b0, B50A_OUT, B49_OUT, B56_Q}, B32_Q);
	reg [3:0] B32_Q;
	always @(posedge CLK) if (CLK_EN) B32_Q <= {1'b0, B50A_OUT, B49_OUT, B56_Q};
	
	assign IPL0 = ~|{~B32_Q[0], B32_Q[2]};
	assign IPL1 = ~|{~B32_Q[1], ~B32_Q[0]};
	
	// Interrupt priority encoder
	// IRQ  IPL
	// xx1: 100 Reset IRQ
	// x10: 101 Timer IRQ
	// 100: 110 VBL IRQ
	// 000: 111 No interrupt

endmodule
module neo_cmc
(
	input             CLK,
	input             PCK2B_EN,
	input      [14:0] PBUS,
	input      [10:0] ADDR,
	input       [1:0] TYPE,
	output reg  [1:0] BANK
);

always @(posedge CLK) begin : pck2b_block
	reg [10:0] old_addr;
	reg        skip;
	reg [0:79] banks;
	reg  [3:0] map[31:0];
	reg  [4:0] line;

	if (PCK2B_EN) begin

		if(ADDR == 'h7E2 && !PBUS[14:12]) begin
			skip <= 0;
			line <= 0;
			BANK <= 1; // for parental advisory (mslug4)
		end

		old_addr <= ADDR;
		if(old_addr == ADDR) begin
			if(TYPE[0]) begin
				if(ADDR[10:8] == 7 && !PBUS[14:12]) begin
					if(&map[line][3:2] && ~skip) begin
						BANK <= map[line][1:0];
						skip <= 1;
					end
					else begin
						line <= line + 1'd1;
						skip <= 0;
					end
				end

				// even words
				if ({ADDR[6],ADDR[0],ADDR[10:8]} == 5) begin
					if(ADDR[7]) map[ADDR[5:1]][2:0] <= {&PBUS[11:8], ~PBUS[1:0]}; // 7580~75BE
					       else map[ADDR[5:1]][3]   <= (PBUS[11:0] == 'h200);     // 7500~753E
				end
			end

			if(TYPE[1]) begin
				// 7500 - 75DF
				if(ADDR[10:8] == 5 && &PBUS[14:12]) banks[{1'b0,ADDR[7:5],3'b000}+{2'b00,ADDR[7:5],2'b00} +:12] <= ~PBUS[11:0];
				BANK <= banks[{ADDR[10:5],1'b0} +:2];
			end
		end

		if(~^TYPE) BANK <= 0;
	end
end

endmodule
module autoanim_sync(
	input CLK,
	input RASTER8,
	input RESETP,
	input [7:0] AA_SPEED,
	output [2:0] AA_COUNT
);

	wire [3:0] D151_Q;

	//wire B91_CO;
	//wire E117_CO;

	//wire E95A_OUT = ~|{E117_CO, 1'b0};	// Used for test mode
	//wire E149_OUT = ~^{CLK, 1'b0};			// Used for test mode
	
	// Timer counters
	//C43 B91(E149_OUT, ~AA_SPEED[3:0], E95A_OUT, 1'b1, 1'b1, 1'b1, , B91_CO);
	//C43 E117(E149_OUT, ~AA_SPEED[7:4], E95A_OUT, 1'b1, B91_CO, 1'b1, , E117_CO);

	// Auto-anim tile counter
	//C43 D151(E149_OUT, 4'b0000, 1'b1, 1'b1, E117_CO, RESETP, D151_Q);
	
	//assign AA_COUNT = D151_Q[2:0];

	reg [7:0] TIMER_CNT;
	reg [3:0] AA_CNT_FULL;
	always @(posedge CLK) begin : raster_block
		reg RASTER8_d;
		RASTER8_d <= RASTER8;
		if (~RASTER8_d & RASTER8) begin
			if (&TIMER_CNT)
				TIMER_CNT <= ~AA_SPEED;
			else
				TIMER_CNT <= TIMER_CNT + 1'd1;

			if (!RESETP)
				AA_CNT_FULL <= 0;
			else if (&TIMER_CNT)
				AA_CNT_FULL <= AA_CNT_FULL + 1'd1;
		end
	end

	assign AA_COUNT = AA_CNT_FULL[2:0];

endmodule
module spram #(parameter ADDRWIDTH=8, DATAWIDTH=8)
(
	input	                 clock,
	input	 [ADDRWIDTH-1:0] address,
	input	 [DATAWIDTH-1:0] data,
	input	                 wren,
	output [DATAWIDTH-1:0] q
);

dpram #(ADDRWIDTH, DATAWIDTH) ram
(
	.clock_a(clock),
	.clock_b(clock),
	.address_a(address),
	.data_a(data),
	.wren_a(wren),
	.q_a(q)
);

endmodule
module watchdog(
	input CLK,
	input DOGE,
	input nLDS, RW,
	input A23I, A22I,
	input [21:17] M68K_ADDR_U,
	//input [12:1] M68K_ADDR_L,
	input WDCLK,
	output nHALT,
	output nRESET,
	input nRST
);

	reg [3:0] WDCNT;
	
	initial
		WDCNT = 4'b0000;
	
	// IMPORTANT:
	// nRESET is an open-collector output on B1, so that the 68k can drive it (RESET instruction)
	// The line has a 4.7k pullup (schematics page 1)
	// nRESET changes state on posedge nBNKB (posedge mclk), but takes a slightly variable amount of time to
	// return high after it is released. Low during 8 frames, released during 8 frames.
	assign nRESET = nRST & ~WDCNT[3];
	assign nHALT = nRESET;	// Yup (these are open-collector)
	
	// $300001 (LDS)
	// 0011000xxxxxxxxxxxxxxxx1
	// MAME says 00110001xxxxxxxxxxxxxxx1 but NEO-B1 doesn't have A16
	wire WDRESET = ~DOGE | &{nRST, ~|{nLDS, RW, A23I, A22I}, M68K_ADDR_U[21:20], ~|{M68K_ADDR_U[19:17]}};
	
	always @(posedge CLK)
	begin : watchdog_block
		reg WDCLK_D;
		WDCLK_D <= WDCLK;

		if (WDRESET)
			WDCNT <= 4'b0000;
		else if (!nRST)
			WDCNT <= 4'b1000;
		else begin
			if (~WDCLK_D & WDCLK)
				WDCNT <= WDCNT + 1'b1;
		end
	end

endmodule
module c1_regs(
	input CLK,
	input nICOM_ZONE,
	input RW,
	inout [15:8] M68K_DATA,
	output [7:0] SDD_RD,
	input [7:0] SDD_WR,
	input nSDZ80R, nSDZ80W, nSDZ80CLR,
	output nSDW
);

	reg [7:0] SDD_LATCH_CMD;
	reg [7:0] SDD_LATCH_REP;
	
	// Z80 command read
	assign SDD_RD = SDD_LATCH_CMD;	//nSDZ80R ? 8'bzzzzzzzz : SDD_LATCH_CMD;
	
	// Z80 reply write
	always @(posedge CLK) begin : sdz_block
		reg nSDZ80W_d;
		nSDZ80W_d <= nSDZ80W;
		if (nSDZ80W & ~nSDZ80W_d)
			SDD_LATCH_REP <= SDD_WR;
	end
	
	// REG_SOUND read
	assign M68K_DATA = (RW & ~nICOM_ZONE) ? SDD_LATCH_REP : 8'bzzzzzzzz;
	
	// REG_SOUND write
	assign nSDW = (RW | nICOM_ZONE);		// Tells Z80 that 68k sent a command
	
	// REG_SOUND write
	always @(posedge CLK)		// Which one has priority ?
	begin : icom_zone_block
		reg nICOM_ZONE_d;
		reg nSDZ80CLR_d;
		nICOM_ZONE_d <= nICOM_ZONE;
		nSDZ80CLR_d <= nSDZ80CLR;

		if (!nSDZ80CLR & nSDZ80CLR_d)
		begin
			SDD_LATCH_CMD <= 8'b00000000;
		end
		else
		if (!nICOM_ZONE & nICOM_ZONE_d) begin
			if (!RW)
				SDD_LATCH_CMD <= M68K_DATA;
		end
	end
	
endmodule
module neo_d0(
	input CLK,
	input CLK_EN_24M_P,
	input CLK_EN_24M_N,
	output CLK_24M,
	input nRESET, nRESETP,
	output CLK_12M,
	output CLK_68KCLK,
	output CLK_68KCLKB,
	output CLK_EN_68K_P,
	output CLK_EN_68K_N,
	output CLK_6MB,
	output CLK_1HB,
	output CLK_EN_12M,
	output CLK_EN_12M_N,
	output CLK_EN_6MB,
	output CLK_EN_1HB,
	input M68K_ADDR_A4,
	input nBITWD0,
	input [5:0] M68K_DATA,
	input [15:11] SDA_H,
	input [4:2] SDA_L,
	input nSDRD, nSDWR, nMREQ, nIORQ,
	output nZ80NMI,
	input nSDW,
	output nSDZ80R, nSDZ80W, nSDZ80CLR,
	output nSDROM, nSDMRD, nSDMWR,
	output SDRD0, SDRD1,
	output n2610CS, n2610RD, n2610WR,
	output nZRAMCS,
	output [2:0] BNK,
	output [2:0] P1_OUT,
	output [2:0] P2_OUT
);
	reg [2:0] REG_BNK;
	reg [5:0] REG_OUT;
	
	// Clock divider part
	clocks_sync CLKS(CLK, CLK_EN_24M_P, CLK_EN_24M_N, nRESETP, CLK_24M, CLK_12M, CLK_68KCLK, CLK_68KCLKB, CLK_EN_68K_P, CLK_EN_68K_N, CLK_6MB, CLK_1HB, CLK_EN_12M, CLK_EN_12M_N, CLK_EN_6MB, CLK_EN_1HB);
	
	// Z80 controller part
	z80ctrl Z80CTRL(CLK, SDA_L, SDA_H, nSDRD, nSDWR, nMREQ, nIORQ, nSDW, nRESET, nZ80NMI, nSDZ80R, nSDZ80W,
				nSDZ80CLR, nSDROM, nSDMRD, nSDMWR, SDRD0, SDRD1, n2610CS, n2610RD, n2610WR, nZRAMCS);
	
	assign {P2_OUT, P1_OUT} = nRESETP ? REG_OUT : 6'b000000;
	assign BNK = nRESETP ? REG_BNK : 3'b000;

	always @(posedge CLK)
	begin : d0_block
		reg nBITWD0_d;
		nBITWD0_d <= nBITWD0;
		if (!nBITWD0 & nBITWD0_d) begin
			if (M68K_ADDR_A4)
				REG_BNK <= M68K_DATA[2:0];
			else
				REG_OUT <= M68K_DATA[5:0];
		end
	end
	
endmodule
module cpu_z80(
	input CLK,
	input CLK4P_EN,
	input CLK4N_EN,
	input nRESET,
	input [7:0] SDD_IN,
	output [7:0] SDD_OUT,
	output [15:0] SDA,
	output nIORQ,
	output nMREQ,
	output nRD, nWR,
	input nBUSRQ,
	output nBUSAK,
	input nINT, nNMI, nWAIT
);

	wire RFSH_n, MREQ_n;
	assign nMREQ = MREQ_n | ~RFSH_n;

	T80pa cpu(
		.RESET_n(nRESET),
		.CLK(CLK),
		.CEN_p(CLK4P_EN),
		.CEN_n(CLK4N_EN),
		.WAIT_n(nWAIT),
		.INT_n(nINT),
		.NMI_n(nNMI),
		.MREQ_n(MREQ_n),
		.IORQ_n(nIORQ),
		.RD_n(nRD),
		.WR_n(nWR),
		.RFSH_n(RFSH_n),
		.BUSRQ_n(nBUSRQ),
		.BUSAK_n(nBUSAK),
		.A(SDA),
		.DI(SDD_IN),
		.DO(SDD_OUT)
	);

endmodule
module cdda
(
	input      CLK,
	input      nRESET,
	input      READ,
	input      WRITE,
	input      [15:0] DIN,
	output     WRITE_READY,
	output reg [15:0] AUDIO_L,
	output reg [15:0] AUDIO_R

);

localparam SECTOR_SIZE = 2352*8/32;
localparam BUFFER_AMOUNT = 2 * SECTOR_SIZE;

reg OLD_WRITE, OLD_READ, LRCK, WR_REQ;

reg [15:0] DATA;
reg [12:0] FILLED_COUNT;

reg [12:0] READ_ADDR, WRITE_ADDR;

wire EMPTY = ~|FILLED_COUNT;
wire FULL = (FILLED_COUNT == BUFFER_AMOUNT);
wire WRITE_CE = ~OLD_WRITE & WRITE;
wire READ_CE = ~OLD_READ & READ;
wire READ_REQ = READ_CE & ~EMPTY;

assign WRITE_READY = (FILLED_COUNT <= (BUFFER_AMOUNT - SECTOR_SIZE)); // Ready to receive sector

always @(posedge CLK) begin
	if (~nRESET) begin
		OLD_WRITE <= 0;
		OLD_READ <= 0;
		LRCK      <= 0;
		READ_ADDR <= 0;
		WRITE_ADDR <= 0;
		FILLED_COUNT <= 0;
	end else begin
		OLD_WRITE <= WRITE;
		OLD_READ <= READ;

		WR_REQ <= 0;
		if (WRITE_CE) begin
			LRCK <= ~LRCK;
			if (~LRCK) begin
				DATA <= DIN;
			end else if(~FULL) begin
				WR_REQ <= 1;
			end
		end

		if (WR_REQ) begin
			if (WRITE_ADDR == BUFFER_AMOUNT-1) begin
				WRITE_ADDR <= 0;
			end else begin
				WRITE_ADDR <= WRITE_ADDR + 1'b1;
			end
		end

		if (READ_REQ) begin
			if (READ_ADDR == BUFFER_AMOUNT-1) begin
				READ_ADDR <= 0;
			end else begin
				READ_ADDR <= READ_ADDR + 1'b1;
			end
			AUDIO_L <= BUFFER_Q[15:0];
			AUDIO_R <= BUFFER_Q[31:16];
		end

		if (READ_CE & EMPTY) begin
			AUDIO_L <= 0;
			AUDIO_R <= 0;
		end

		FILLED_COUNT <= FILLED_COUNT + WR_REQ - READ_REQ;
	end
end

reg [31:0] BUFFER[BUFFER_AMOUNT-1:0];
reg [31:0] BUFFER_Q;
always @(posedge CLK) begin
	BUFFER_Q <= BUFFER[READ_ADDR];
	if (WR_REQ) begin
		BUFFER[WRITE_ADDR] <= { DIN, DATA };
	end
end

endmodule
module pll (
		input  wire        refclk,            //            refclk.clk
		input  wire        rst,               //             reset.reset
		output wire        outclk_0,          //           outclk0.clk
		output wire        locked             //            locked.export
	);

	pll_0002 pll_inst (
		.refclk            (refclk),            //            refclk.clk
		.rst               (rst),               //             reset.reset
		.outclk_0          (outclk_0),          //           outclk0.clk
		.locked            (locked)             //            locked.export
	);

endmodule
module  pll_0002(
	input  wire refclk,
	input  wire rst,
	output wire outclk_0,
	output wire locked,
	input  wire [63:0] reconfig_to_pll,
	output wire [63:0] reconfig_from_pll
);
`ifdef CYCLONEV
	altera_pll #(
		.fractional_vco_multiplier("true"),
		.reference_clock_frequency("50.0 MHz"),
		.pll_fractional_cout(32),
		.pll_dsm_out_sel("1st_order"),
		.operation_mode("direct"),
		.number_of_clocks(1),
		.output_clock_frequency0("53.693175 MHz"),
		.phase_shift0("0 ps"),
		.duty_cycle0(50),
		.pll_type("Cyclone V"),
		.pll_subtype("Reconfigurable"),
		.m_cnt_hi_div(4),
		.m_cnt_lo_div(4),
		.n_cnt_hi_div(256),
		.n_cnt_lo_div(256),
		.m_cnt_bypass_en("false"),
		.n_cnt_bypass_en("true"),
		.m_cnt_odd_div_duty_en("false"),
		.n_cnt_odd_div_duty_en("false"),
		.c_cnt_hi_div0(4),
		.c_cnt_lo_div0(4),
		.c_cnt_prst0(1),
		.c_cnt_ph_mux_prst0(0),
		.c_cnt_in_src0("ph_mux_clk"),
		.c_cnt_bypass_en0("false"),
		.c_cnt_odd_div_duty_en0("false"),
		.c_cnt_hi_div1(1),
		.c_cnt_lo_div1(1),
		.c_cnt_prst1(1),
		.pll_vco_div(2),
		.pll_cp_current(30),
		.pll_bwctrl(2000),
		.pll_output_clk_frequency("429.5454 MHz"),
		.pll_fractional_division("2537930535"),
		.pll_fbclk_mux_1("glb"),
		.pll_fbclk_mux_2("m_cnt"),
		.pll_m_cnt_in_src("ph_mux_clk"),
		.pll_slf_rst("true")
	) altera_pll_i (
		.rst	(rst),
		.outclk	({outclk_0}),
		.locked	(locked),
		.reconfig_to_pll	(reconfig_to_pll),
		.fboutclk	( ),
		.fbclk	(1'b0),
		.refclk	(refclk),
		.reconfig_from_pll	(reconfig_from_pll)
	);
`else
	ALTPLL #(
		.BANDWIDTH_TYPE("AUTO"),
		.CLK0_DIVIDE_BY(10'd14),
		.CLK0_DUTY_CYCLE(6'd50),
		.CLK0_MULTIPLY_BY(10'd15),
		.CLK0_PHASE_SHIFT(1'd0),
		.COMPENSATE_CLOCK("CLK0"),
		.INCLK0_INPUT_FREQUENCY(15'd20000),
		.OPERATION_MODE("NORMAL")
	) CORE_PLL (
		.ARESET(1'd0),
		.CLKENA(5'd31),
		.EXTCLKENA(4'd15),
		.FBIN(1'd1),
		.INCLK(refclk),
		.PFDENA(1'd1),
		.PLLENA(1'd1),
		.CLK({outclk_0}),
		.LOCKED(locked)
	);
`endif
endmodule