dakies/OSS_Verilog huggingface dataset:
module ddr3_p0_reset_sync(
	reset_n,
	clk,
	reset_n_sync
);

parameter RESET_SYNC_STAGES = 4;
parameter NUM_RESET_OUTPUT = 1;

input	reset_n;
input	clk;
output	[NUM_RESET_OUTPUT-1:0] reset_n_sync;




// identify the synchronizer chain so that Quartus can analyze metastability.
// Since these resets are localized to the PHY alone, make them routed locally
// to avoid using global networks.
(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS; -name GLOBAL_SIGNAL OFF"}*) reg	[RESET_SYNC_STAGES+NUM_RESET_OUTPUT-2:0] reset_reg /*synthesis dont_merge */;

generate
genvar i;
	for (i=0; i<RESET_SYNC_STAGES+NUM_RESET_OUTPUT-1; i=i+1)
	begin: reset_stage
		always @(posedge clk or negedge reset_n)
		begin
			if (~reset_n)
				reset_reg[i] <= 1'b0;
			else
			begin
				if (i==0)
					reset_reg[i] <= 1'b1;
				else if (i < RESET_SYNC_STAGES)
					reset_reg[i] <= reset_reg[i-1];
				else
					reset_reg[i] <= reset_reg[RESET_SYNC_STAGES-2];
				
			end
		end
	end
endgenerate

	assign reset_n_sync = reset_reg[RESET_SYNC_STAGES+NUM_RESET_OUTPUT-2:RESET_SYNC_STAGES-1];

endmodule
module rw_manager_inst_ROM_reg(
        rdaddress,
        clock,
        data,
        wraddress,
        wren,
        q);


parameter INST_ROM_DATA_WIDTH = "";
parameter INST_ROM_ADDRESS_WIDTH = "";

input [(INST_ROM_ADDRESS_WIDTH-1):0]  rdaddress;
input     clock;
input [(INST_ROM_ADDRESS_WIDTH-1):0] wraddress;
input [(INST_ROM_DATA_WIDTH-1):0] data;
input wren; 
output reg [(INST_ROM_DATA_WIDTH-1):0]  q;

reg [(INST_ROM_DATA_WIDTH-1):0] inst_mem[(2**INST_ROM_ADDRESS_WIDTH-1):0];

always @(posedge clock)

begin
  if (wren)
  inst_mem[wraddress]<= data;
  q <= inst_mem[rdaddress];

end



endmodule
module rw_manager_datamux(datain, sel, dataout);
	parameter DATA_WIDTH = 8;
	parameter SELECT_WIDTH = 1;
	parameter NUMBER_OF_CHANNELS = 2;

	input [NUMBER_OF_CHANNELS * DATA_WIDTH - 1 : 0] datain;
	input [SELECT_WIDTH - 1 : 0] sel;
	output [DATA_WIDTH - 1 : 0] dataout;

	wire [DATA_WIDTH - 1 : 0] vectorized_data [0 : NUMBER_OF_CHANNELS - 1];

	assign dataout = vectorized_data[sel];

	genvar c;
	generate
		for(c = 0 ; c < NUMBER_OF_CHANNELS ; c = c + 1) 
		begin : channel_iterator
			assign vectorized_data[c] = datain[(c + 1) * DATA_WIDTH - 1 : c * DATA_WIDTH];
		end
	endgenerate
	
`ifdef ADD_UNIPHY_SIM_SVA
	assert property (@datain NUMBER_OF_CHANNELS == 2**SELECT_WIDTH) else
	    $error("%t, [DATAMUX ASSERT] NUMBER_OF_CHANNELS PARAMETER is incorrect, NUMBER_OF_CHANNELS = %d, 2**SELECT_WIDTH = %d", $time, NUMBER_OF_CHANNELS, 2**SELECT_WIDTH);
`endif

endmodule
module rw_manager_m10_inst_ROM (
	clock,
	rdaddress,
	q);
	
	input	  clock;
	input	[6:0]  rdaddress;
	output	[19:0]  q;
	
	reg	[19:0]  q;
	
	wire	[6:0]  rdaddress_r;
  assign  rdaddress_r =   rdaddress;
	
always @ (posedge clock)
    case(rdaddress_r)
'h00 : q <= 'h080000;
'h01 : q <= 'h000780;
'h02 : q <= 'h080680;
'h03 : q <= 'h000180;
'h04 : q <= 'h080680;
'h05 : q <= 'h000200;
'h06 : q <= 'h080680;
'h07 : q <= 'h000280;
'h08 : q <= 'h080680;
'h09 : q <= 'h000300;
'h0A : q <= 'h080680;
'h0B : q <= 'h000380;
'h0C : q <= 'h080680;
'h0D : q <= 'h000100;
'h0E : q <= 'h080680;
'h0F : q <= 'h000800;
'h10 : q <= 'h008680;
'h11 : q <= 'h000880;
'h12 : q <= 'h00A680;
'h13 : q <= 'h080680;
'h14 : q <= 'h000900;
'h15 : q <= 'h080680;
'h16 : q <= 'h000980;
'h17 : q <= 'h008680;
'h18 : q <= 'h080680;
'h19 : q <= 'h000B68;
'h1A : q <= 'h00CCE8;
'h1B : q <= 'h000AE8;
'h1C : q <= 'h008CE8;
'h1D : q <= 'h000B88;
'h1E : q <= 'h00EC88;
'h1F : q <= 'h000A08;
'h20 : q <= 'h00AC88;
'h21 : q <= 'h080680;
'h22 : q <= 'h00CE00;
'h23 : q <= 'h00CD80;
'h24 : q <= 'h00E700;
'h25 : q <= 'h000C00;
'h26 : q <= 'h020CE0;
'h27 : q <= 'h020CE0;
'h28 : q <= 'h000D00;
'h29 : q <= 'h000680;
'h2A : q <= 'h000680;
'h2B : q <= 'h060E80;
'h2C : q <= 'h061080;
'h2D : q <= 'h00A680;
'h2E : q <= 'h008680;
'h2F : q <= 'h080680;
'h30 : q <= 'h00CE00;
'h31 : q <= 'h00CD80;
'h32 : q <= 'h00E700;
'h33 : q <= 'h000C00;
'h34 : q <= 'h030CE0;
'h35 : q <= 'h030CE0;
'h36 : q <= 'h000D00;
'h37 : q <= 'h000680;
'h38 : q <= 'h000680;
'h39 : q <= 'h070E80;
'h3A : q <= 'h071080;
'h3B : q <= 'h00A680;
'h3C : q <= 'h008680;
'h3D : q <= 'h080680;
'h3E : q <= 'h001158;
'h3F : q <= 'h0006D8;
'h40 : q <= 'h080680;
'h41 : q <= 'h040E88;
'h42 : q <= 'h041088;
'h43 : q <= 'h040F68;
'h44 : q <= 'h0410E8;
'h45 : q <= 'h00A680;
'h46 : q <= 'h040FE8;
'h47 : q <= 'h0410E8;
'h48 : q <= 'h041008;
'h49 : q <= 'h041088;
'h4A : q <= 'h001100;
'h4B : q <= 'h00C680;
'h4C : q <= 'h008680;
'h4D : q <= 'h00E680;
'h4E : q <= 'h080680;
'h4F : q <= 'h000000;
'h50 : q <= 'h000000;
'h51 : q <= 'h00A000;
'h52 : q <= 'h008000;
'h53 : q <= 'h080000;
'h54 : q <= 'h000080;
'h55 : q <= 'h000080;
'h56 : q <= 'h000080;
'h57 : q <= 'h000080;
'h58 : q <= 'h00A080;
'h59 : q <= 'h008080;
'h5A : q <= 'h080080;
'h5B : q <= 'h008680;
'h5C : q <= 'h00A680;
'h5D : q <= 'h080680;
'h5E : q <= 'h040F08;
'h5F : q <= 'h080680;
'h60 : q <= 'h000000;
'h61 : q <= 'h000000;
'h62 : q <= 'h000000;
'h63 : q <= 'h000000;
'h64 : q <= 'h000000;
'h65 : q <= 'h000000;
'h66 : q <= 'h000000;
'h67 : q <= 'h000000;
'h68 : q <= 'h000000;
'h69 : q <= 'h000000;
'h6A : q <= 'h000000;
'h6B : q <= 'h000000;
'h6C : q <= 'h000000;
'h6D : q <= 'h000000;
'h6E : q <= 'h000000;
'h6F : q <= 'h000000;
'h70 : q <= 'h000000;
'h71 : q <= 'h000000;
'h72 : q <= 'h000000;
'h73 : q <= 'h000000;
'h74 : q <= 'h000000;
'h75 : q <= 'h000000;
'h76 : q <= 'h000000;
'h77 : q <= 'h000000;
'h78 : q <= 'h000000;
'h79 : q <= 'h000000;
'h7A : q <= 'h000000;
'h7B : q <= 'h000000;
'h7C : q <= 'h000000;
'h7D : q <= 'h000000;
'h7E : q <= 'h000000;
'h7F : q <= 'h000000;
        default : q <= 0;
    endcase
endmodule
module axil_reg_if_rd #
(
    // Width of data bus in bits
    parameter DATA_WIDTH = 32,
    // Width of address bus in bits
    parameter ADDR_WIDTH = 32,
    // Width of wstrb (width of data bus in words)
    parameter STRB_WIDTH = (DATA_WIDTH/8),
    // Timeout delay (cycles)
    parameter TIMEOUT = 4
)
(
    input  wire                   clk,
    input  wire                   rst,

    /*
     * AXI-Lite slave interface
     */
    input  wire [ADDR_WIDTH-1:0]  s_axil_araddr,
    input  wire [2:0]             s_axil_arprot,
    input  wire                   s_axil_arvalid,
    output wire                   s_axil_arready,
    output wire [DATA_WIDTH-1:0]  s_axil_rdata,
    output wire [1:0]             s_axil_rresp,
    output wire                   s_axil_rvalid,
    input  wire                   s_axil_rready,

    /*
     * Register interface
     */
    output wire [ADDR_WIDTH-1:0]  reg_rd_addr,
    output wire                   reg_rd_en,
    input  wire [DATA_WIDTH-1:0]  reg_rd_data,
    input  wire                   reg_rd_wait,
    input  wire                   reg_rd_ack
);

parameter TIMEOUT_WIDTH = $clog2(TIMEOUT);

reg [TIMEOUT_WIDTH-1:0] timeout_count_reg = 0, timeout_count_next;

reg [ADDR_WIDTH-1:0] s_axil_araddr_reg = {ADDR_WIDTH{1'b0}}, s_axil_araddr_next;
reg s_axil_arvalid_reg = 1'b0, s_axil_arvalid_next;
reg [DATA_WIDTH-1:0] s_axil_rdata_reg = {DATA_WIDTH{1'b0}}, s_axil_rdata_next;
reg s_axil_rvalid_reg = 1'b0, s_axil_rvalid_next;

reg reg_rd_en_reg = 1'b0, reg_rd_en_next;

assign s_axil_arready = !s_axil_arvalid_reg;
assign s_axil_rdata = s_axil_rdata_reg;
assign s_axil_rresp = 2'b00;
assign s_axil_rvalid = s_axil_rvalid_reg;

assign reg_rd_addr = s_axil_araddr_reg;
assign reg_rd_en = reg_rd_en_reg;

always @* begin
    timeout_count_next = timeout_count_reg;

    s_axil_araddr_next = s_axil_araddr_reg;
    s_axil_arvalid_next = s_axil_arvalid_reg;
    s_axil_rdata_next = s_axil_rdata_reg;
    s_axil_rvalid_next = s_axil_rvalid_reg && !s_axil_rready;

    if (reg_rd_en_reg && (reg_rd_ack || timeout_count_reg == 0)) begin
        s_axil_arvalid_next = 1'b0;
        s_axil_rdata_next = reg_rd_data;
        s_axil_rvalid_next = 1'b1;
    end

    if (!s_axil_arvalid_reg) begin
        s_axil_araddr_next = s_axil_araddr;
        s_axil_arvalid_next = s_axil_arvalid;
        timeout_count_next = TIMEOUT-1;
    end

    if (reg_rd_en && !reg_rd_wait && timeout_count_reg != 0)begin
        timeout_count_next = timeout_count_reg - 1;
    end

    reg_rd_en_next = s_axil_arvalid_next && !s_axil_rvalid_next;
end

always @(posedge clk) begin
    timeout_count_reg <= timeout_count_next;

    s_axil_araddr_reg <= s_axil_araddr_next;
    s_axil_arvalid_reg <= s_axil_arvalid_next;
    s_axil_rdata_reg <= s_axil_rdata_next;
    s_axil_rvalid_reg <= s_axil_rvalid_next;

    reg_rd_en_reg <= reg_rd_en_next;

    if (rst) begin
        s_axil_arvalid_reg <= 1'b0;
        s_axil_rvalid_reg <= 1'b0;
        reg_rd_en_reg <= 1'b0;
    end
end

endmodule
module priority_encoder #
(
    parameter WIDTH = 4,
    // LSB priority selection
    parameter LSB_HIGH_PRIORITY = 0
)
(
    input  wire [WIDTH-1:0]         input_unencoded,
    output wire                     output_valid,
    output wire [$clog2(WIDTH)-1:0] output_encoded,
    output wire [WIDTH-1:0]         output_unencoded
);

parameter LEVELS = WIDTH > 2 ? $clog2(WIDTH) : 1;
parameter W = 2**LEVELS;

// pad input to even power of two
wire [W-1:0] input_padded = {{W-WIDTH{1'b0}}, input_unencoded};

wire [W/2-1:0] stage_valid[LEVELS-1:0];
wire [W/2-1:0] stage_enc[LEVELS-1:0];

generate
    genvar l, n;

    // process input bits; generate valid bit and encoded bit for each pair
    for (n = 0; n < W/2; n = n + 1) begin : loop_in
        assign stage_valid[0][n] = |input_padded[n*2+1:n*2];
        if (LSB_HIGH_PRIORITY) begin
            // bit 0 is highest priority
            assign stage_enc[0][n] = !input_padded[n*2+0];
        end else begin
            // bit 0 is lowest priority
            assign stage_enc[0][n] = input_padded[n*2+1];
        end
    end

    // compress down to single valid bit and encoded bus
    for (l = 1; l < LEVELS; l = l + 1) begin : loop_levels
        for (n = 0; n < W/(2*2**l); n = n + 1) begin : loop_compress
            assign stage_valid[l][n] = |stage_valid[l-1][n*2+1:n*2];
            if (LSB_HIGH_PRIORITY) begin
                // bit 0 is highest priority
                assign stage_enc[l][(n+1)*(l+1)-1:n*(l+1)] = stage_valid[l-1][n*2+0] ? {1'b0, stage_enc[l-1][(n*2+1)*l-1:(n*2+0)*l]} : {1'b1, stage_enc[l-1][(n*2+2)*l-1:(n*2+1)*l]};
            end else begin
                // bit 0 is lowest priority
                assign stage_enc[l][(n+1)*(l+1)-1:n*(l+1)] = stage_valid[l-1][n*2+1] ? {1'b1, stage_enc[l-1][(n*2+2)*l-1:(n*2+1)*l]} : {1'b0, stage_enc[l-1][(n*2+1)*l-1:(n*2+0)*l]};
            end
        end
    end
endgenerate

assign output_valid = stage_valid[LEVELS-1];
assign output_encoded = stage_enc[LEVELS-1];
assign output_unencoded = 1 << output_encoded;

endmodule
module test_axil_ram;

// Parameters
parameter DATA_WIDTH = 32;
parameter ADDR_WIDTH = 16;
parameter STRB_WIDTH = DATA_WIDTH/8;
parameter PIPELINE_OUTPUT = 0;

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg [ADDR_WIDTH-1:0] s_axil_awaddr = 0;
reg [2:0] s_axil_awprot = 0;
reg s_axil_awvalid = 0;
reg [DATA_WIDTH-1:0] s_axil_wdata = 0;
reg [STRB_WIDTH-1:0] s_axil_wstrb = 0;
reg s_axil_wvalid = 0;
reg s_axil_bready = 0;
reg [ADDR_WIDTH-1:0] s_axil_araddr = 0;
reg [2:0] s_axil_arprot = 0;
reg s_axil_arvalid = 0;
reg s_axil_rready = 0;

// Outputs
wire s_axil_awready;
wire s_axil_wready;
wire [1:0] s_axil_bresp;
wire s_axil_bvalid;
wire s_axil_arready;
wire [DATA_WIDTH-1:0] s_axil_rdata;
wire [1:0] s_axil_rresp;
wire s_axil_rvalid;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        s_axil_awaddr,
        s_axil_awprot,
        s_axil_awvalid,
        s_axil_wdata,
        s_axil_wstrb,
        s_axil_wvalid,
        s_axil_bready,
        s_axil_araddr,
        s_axil_arprot,
        s_axil_arvalid,
        s_axil_rready
    );
    $to_myhdl(
        s_axil_awready,
        s_axil_wready,
        s_axil_bresp,
        s_axil_bvalid,
        s_axil_arready,
        s_axil_rdata,
        s_axil_rresp,
        s_axil_rvalid
    );

    // dump file
    $dumpfile("test_axil_ram.lxt");
    $dumpvars(0, test_axil_ram);
end

axil_ram #(
    .DATA_WIDTH(DATA_WIDTH),
    .ADDR_WIDTH(ADDR_WIDTH),
    .STRB_WIDTH(STRB_WIDTH),
    .PIPELINE_OUTPUT(PIPELINE_OUTPUT)
)
UUT (
    .clk(clk),
    .rst(rst),
    .s_axil_awaddr(s_axil_awaddr),
    .s_axil_awprot(s_axil_awprot),
    .s_axil_awvalid(s_axil_awvalid),
    .s_axil_awready(s_axil_awready),
    .s_axil_wdata(s_axil_wdata),
    .s_axil_wstrb(s_axil_wstrb),
    .s_axil_wvalid(s_axil_wvalid),
    .s_axil_wready(s_axil_wready),
    .s_axil_bresp(s_axil_bresp),
    .s_axil_bvalid(s_axil_bvalid),
    .s_axil_bready(s_axil_bready),
    .s_axil_araddr(s_axil_araddr),
    .s_axil_arprot(s_axil_arprot),
    .s_axil_arvalid(s_axil_arvalid),
    .s_axil_arready(s_axil_arready),
    .s_axil_rdata(s_axil_rdata),
    .s_axil_rresp(s_axil_rresp),
    .s_axil_rvalid(s_axil_rvalid),
    .s_axil_rready(s_axil_rready)
);

endmodule
module IF
(
	//from pc 
	input wire  [63:0] inst_addr_i     ,
	//I-Cache访问接口
	//to icache
	output wire [11:0] icache_req_addr ,
	output wire        icache_req_valid,
	output wire        icache_req_rw   ,
	//from icache
	input wire [31:0]  icache_data_read,
	input wire         icache_ready    ,
	input wire         icache_hit      ,
	//to if_id
	output wire [63:0] inst_addr_o     ,
	output wire [31:0] inst_o          ,
	//to ctrl
	output wire        hold_flag_if_o
);

	assign inst_addr_o   = inst_addr_i ;

	assign icache_req_addr  = inst_addr_i[13:2];
	assign icache_req_valid = 1'b1             ;
	assign icache_req_rw    = 1'b0             ;
	
	assign inst_o = (icache_ready == 1'b1) ? icache_data_read:32'h00000013;

	assign hold_flag_if_o = (icache_hit == 1'b0 && icache_ready == 1'b1) ? 1'b0:1'b1;
 
endmodule
module ROM
(
	input  wire       clk            ,
	input  wire       rst            ,
	
	//AXI4-Lite总线接口 slave
	//写地址
	input wire [11:0] rom_axi_awaddr ,
	input wire        rom_axi_awvalid,
	output reg        rom_axi_awready,
	//写数据
	input wire [127:0]rom_axi_wdata  ,
	input wire [7 :0] rom_axi_wstrb  ,
	input wire        rom_axi_wvalid ,
	output reg        rom_axi_wready ,
	//读地址
	input wire [11:0] rom_axi_araddr ,
	input wire        rom_axi_arvalid,
	output reg        rom_axi_arready,
	//读数据
	output reg [127:0]rom_axi_rdata  ,
	output reg        rom_axi_rvalid ,
	output reg [2 :0] rom_axi_rlast  ,
	input wire        rom_axi_rready
);

	reg [31:0] rom[0:1023];

	reg [11:0]  addr;
	reg         we  ;
	reg [127:0] dout;
	reg [127:0] din ;

	wire axi_whsk = rom_axi_awvalid & rom_axi_wvalid                                                   ;//写通道握手
	wire axi_rhsk = rom_axi_arvalid & (~rom_axi_rvalid | (rom_axi_rready & rom_axi_rvalid)) & ~axi_whsk;

	//读响应控制
	always @(posedge clk) 
		begin
			if(rst == 1'b1) begin
				rom_axi_rvalid <= 1'b0;
				rom_axi_rlast  <= 1'b0;
			end
			else begin
				if(axi_rhsk) begin
					rom_axi_rvalid <= 1'b1;
				end
				else if(rom_axi_rvalid & rom_axi_rready) begin
					rom_axi_rvalid <= 1'b0;
				end
				else begin
					rom_axi_rvalid <= rom_axi_rvalid;
				end
			end
		end

	always @(*)
		begin
			rom_axi_awready = axi_whsk     ;
			rom_axi_wready  = axi_whsk     ;
			rom_axi_rdata   = dout         ;
			rom_axi_arready = axi_rhsk     ;
			din             = rom_axi_wdata;
			if(axi_whsk) begin
				addr = rom_axi_awaddr;
				we   = 1'b1          ;
			end
			else begin
				if(axi_rhsk) begin
					addr = rom_axi_araddr;
					we   = 1'b0          ;
				end
				else begin
					addr = 12'b0;
					we   = 1'b0 ;
				end
			end
		end

	always @(posedge clk) 
		begin
			if(we == 1'b1) begin
				rom[addr + 3] <= din[127:96];
				rom[addr + 2] <= din[95 :64];
				rom[addr + 1] <= din[63 :32];
				rom[addr    ] <= din[31 :0 ];
			end
		end
	
	always @(*)
		begin
			if(rst == 1'b1) begin
				dout = 128'b0;
			end
			else begin
				dout = {rom[addr+3], rom[addr+2], rom[addr+1], rom[addr]};
			end
		end

endmodule
module RAM
(
	input  wire       clk            ,
	input  wire       rst            ,
	
	//AXI4-Lite总线接口 slave
	//写地址
	input wire [11:0]  ram_axi_awaddr ,
	input wire         ram_axi_awvalid,
	output reg         ram_axi_awready,
	//写数据 
	input wire [255:0] ram_axi_wdata  ,
	input wire [7 :0]  ram_axi_wstrb  ,
	input wire         ram_axi_wvalid ,
	output reg         ram_axi_wready ,
	//读地址 
	input wire [11:0]  ram_axi_araddr ,
	input wire         ram_axi_arvalid,
	output reg         ram_axi_arready,
	//读数据 
	output reg [255:0] ram_axi_rdata  ,
	output reg         ram_axi_rvalid ,
	input wire         ram_axi_rready
);

	reg [63:0] ram[0:1023];

	reg [11:0]  addr;
	reg         we  ;
	reg [255:0]  dout;
	reg [255:0]  din ;

	wire axi_whsk = ram_axi_awvalid & ram_axi_wvalid                                                   ;//写通道握手
	wire axi_rhsk = ram_axi_arvalid & (~ram_axi_rvalid | (ram_axi_rready & ram_axi_rvalid)) & ~axi_whsk;

	//读响应控制
	always @(posedge clk) 
		begin
			if(rst == 1'b1) begin
				ram_axi_rvalid <= 1'b0;
			end
			else begin
				if(axi_rhsk) begin
					ram_axi_rvalid <= 1'b1;
				end
				else if(ram_axi_rvalid & ram_axi_rready) begin
					ram_axi_rvalid <= 1'b0;
				end
				else begin
					ram_axi_rvalid <= ram_axi_rvalid;
				end
			end
		end

	always @(*)
		begin
			ram_axi_awready = axi_whsk     ;
			ram_axi_wready  = axi_whsk     ;
			ram_axi_rdata   = dout         ;
			ram_axi_arready = axi_rhsk     ;
			din             = ram_axi_wdata;
			if(axi_whsk) begin
				addr = ram_axi_awaddr;
				we   = 1'b1                ;
			end
			else begin
				if(axi_rhsk) begin
					addr = ram_axi_araddr;
					we   = 1'b0          ;
				end
				else begin
					addr = 12'b0;
					we   = 1'b0 ;
				end
			end
		end

	always @(posedge clk) 
		begin
			if(we == 1'b1) begin
				ram[addr + 3] <= din[255:192];
				ram[addr + 2] <= din[191:128];
				ram[addr + 1] <= din[127:64 ];
				ram[addr    ] <= din[63 :0  ];
			end
		end
	
	always @(*)
		begin
			if(rst == 1'b1) begin
				dout = 256'b0;
			end
			else if(ram_axi_awaddr == ram_axi_araddr) begin
				dout = din;
			end
			else begin
				dout = {ram[addr+3], ram[addr+2], ram[addr+1], ram[addr]};
			end
		end

endmodule
module DFF_SET 
#
(
	parameter DW = 32
)
(
	input  wire          clk        ,
	input  wire          rst        ,
	input  wire [1   :0] hold_flag_i,
	input  wire [DW-1:0] set_data   ,
	input  wire [DW-1:0] data_i     ,
	output reg  [DW-1:0] data_o
);

	always @(posedge clk)
		begin
			if(rst == 1'b1 || hold_flag_i==2'b01) begin
				data_o <= set_data;
			end
			else if(hold_flag_i==2'b10) begin
				data_o <= data_o;
			end
			else begin
				data_o <= data_i;
			end
		end

endmodule
module IF_ID
(
	input wire         clk        ,
	input wire         rst        ,
	//from ctrl
	input wire  [1 :0] hold_flag_i,
	//from if
	input wire  [63:0] inst_addr_i,
	input wire  [31:0] inst_i ,
	//to id
	output wire [63:0] inst_addr_o,
	output wire [31:0] inst_o
);

	/*reg rom_flag;
	
	always @(posedge clk) 
		begin
			if(rst == 1'b1 | hold_flag_i == 2'b01) begin
				rom_flag <= 1'b0;
			end
			else begin
				rom_flag <= 1'b1;
			end
		end
	
	assign rom_inst_o = rom_flag?rom_inst_i:64'h0000_0013;
	
	//wire [63:0] rom_inst_t;

	//assign rom_inst_t = {32'b0, rom_inst_i};*/

	DFF_SET 
	#
	(
		.DW(64)
	) 
	dff1
	(
		.clk        (clk        ),
		.rst        (rst        ),
		.hold_flag_i(hold_flag_i),
		.set_data   (64'b0      ),
	    .data_i     (inst_addr_i),
        .data_o     (inst_addr_o)
	);
		
	DFF_SET 
	#
	(
		.DW(32)
	) 
	dff2
	(
		.clk        (clk          ),
		.rst        (rst          ),
		.hold_flag_i(hold_flag_i  ),
		.set_data   (`INST_NOP),
	    .data_i     (inst_i   ),
        .data_o     (inst_o   )
	);
		
endmodule
module WB
(
	input wire [4 :0]  rd_addr_i,
	input wire [63:0]  rd_data_i,
	input wire         rd_wen_i ,
	//to regs
	output wire [4 :0] rd_addr_o,
	output wire [63:0] rd_data_o,
	output wire        rd_wen_o 
);

	assign rd_addr_o = rd_addr_i;
	assign rd_data_o = rd_data_i;
	assign rd_wen_o  = rd_wen_i ;

endmodule
module CTRL
(
	input  wire [63:0] jump_addr_i      ,
	input  wire        jump_en_i        ,
	input  wire        hold_flag_ex_i   ,
	input  wire        hold_flag_clint_i,
	input  wire        hold_flag_mem_i  ,
	input  wire        hold_flag_if_i   ,
	output reg  [63:0] jump_addr_o      ,
	output reg         jump_en_o        ,
	output reg  [1 :0] hold_flag_o      ,
	output reg         mem_en
);

	always @(*)
		begin
			jump_addr_o = jump_addr_i;
			jump_en_o   = jump_en_i  ;
			if(jump_en_i || hold_flag_ex_i || hold_flag_clint_i) begin
				hold_flag_o = 2'b01;
				mem_en      = 1'b0 ;
			end
			else if (hold_flag_mem_i) begin
				hold_flag_o = 2'b10;
				mem_en      = 1'b1 ;
			end
			else if (hold_flag_if_i) begin
				hold_flag_o = 2'b10;
				mem_en      = 1'b0 ;
			end
			else begin
				hold_flag_o = 2'b11;
				mem_en      = 1'b0 ;
			end
		end

endmodule
module MEM_WB
(
	input  wire        clk      ,
	input  wire        rst      ,
	//from mem
	input wire [4 :0] rd_addr_i ,
	input wire [63:0] rd_data_i ,
	input wire        rd_wen_i  , 
	//to wb
	output wire [4 :0] rd_addr_o,
	output wire [63:0] rd_data_o,
	output wire        rd_wen_o 
);

	DFF_SET 
	#
	(
		.DW(5)
	) 
	dff1
	(
		.clk        (clk      ),
		.rst        (rst      ),
		.hold_flag_i(2'b00    ),
		.set_data   (5'b0     ),
	    .data_i     (rd_addr_i),
        .data_o     (rd_addr_o)
	);
	
	DFF_SET 
	#
	(
		.DW(64)
	) 
	dff2
	(
		.clk        (clk      ),
		.rst        (rst      ),
		.hold_flag_i(2'b00    ),
		.set_data   (64'b0    ),
	    .data_i     (rd_data_i),
        .data_o     (rd_data_o)
	);
	
	DFF_SET 
	#
	(
		.DW(1)
	) 
	dff3
	(
		.clk        (clk     ),
		.rst        (rst     ),
		.hold_flag_i(2'b00   ),
		.set_data   (1'b0    ),
	    .data_i     (rd_wen_i),
        .data_o     (rd_wen_o)
	);

endmodule
module CHECK
(
	//from id
	input wire [4 :0] rs1_addr_i       ,
	input wire [4 :0] rs2_addr_i       ,
	//from ex
	input wire [63:0] ram_addr_i       ,
	input wire        ram_req_i        ,
	//from ex                          
	input wire [4 :0] ex_rd_addr_i     ,
	input wire [63:0] ex_rd_data_i     ,
	input wire        ex_rd_wen_i      ,
	//from ex_mem mem                     
	input wire [4 :0] mem_rd_addr_i    ,
	input wire [63:0] mem_rd_data_i    ,
	input wire        mem_rd_wen_i     ,
	//input wire        ex_mem_ram_we_i  ,
	//input wire [63:0] ex_mem_ram_addr_i,
	//input wire [63:0] ex_mem_ram_data_i,
	//input wire        ex_mem_ram_req_i ,
	//to id 
	output reg [63:0] rs1_data_o       ,
	output reg [63:0] rs2_data_o       ,
	output reg        rs1_valid        ,
	output reg        rs2_valid        
	//to ex                            
	//output reg [63:0] ram_data_o       ,
	//output reg        ram_data_valid
);

	//check ram_addr_i
	/*always @(*)
		begin
			if(ram_req_i == 1'b1 && ex_mem_ram_we_i == 1'b1 && ex_mem_ram_req_i == 1'b1 && ram_addr_i == ex_mem_ram_addr_i) begin
				ram_data_o     = ex_mem_ram_data_i;
				ram_data_valid = 1'b1             ;
			end
			else begin
				ram_data_o     = 64'b0;
				ram_data_valid = 1'b0 ;
			end
		end*/
	
	//check rs1_addr_i
	always @(*)
		begin
			if(rs1_addr_i == ex_rd_addr_i && ex_rd_wen_i == 1'b1 && rs1_addr_i != 5'b0) begin
				rs1_data_o = ex_rd_data_i;
				rs1_valid  = 1'b1        ;
			end
			else if(rs1_addr_i == mem_rd_addr_i && mem_rd_wen_i == 1'b1 && rs1_addr_i != 5'b0) begin
				rs1_data_o = mem_rd_data_i;
				rs1_valid  = 1'b1         ;
			end
			else if(rs1_addr_i == 5'b0) begin
				rs1_data_o = 64'b0;
				rs1_valid  = 1'b1 ;
			end
			else begin
				rs1_data_o = 64'b0;
				rs1_valid  = 1'b0 ;
			end
		end
		
	//chech rs2_addr_i
	always @(*)
		begin
			if(rs2_addr_i == ex_rd_addr_i && ex_rd_wen_i == 1'b1 && rs2_addr_i != 5'b0) begin
				rs2_data_o = ex_rd_data_i;
				rs2_valid  = 1'b1        ;
			end
			else if(rs2_addr_i == mem_rd_addr_i && mem_rd_wen_i == 1'b1 && rs2_addr_i != 5'b0) begin
				rs2_data_o = mem_rd_data_i;
				rs2_valid  = 1'b1         ;
			end
			else if(rs2_addr_i == 5'b0) begin
				rs2_data_o = 64'b0;
				rs2_valid  = 1'b1 ;
			end
			else begin
				rs2_data_o = 64'b0;
				rs2_valid  = 1'b0 ;
			end
		end

endmodule
module REGS
(
	input wire        clk         ,
	input wire        rst         ,
	//from id         
	input wire [4:0]  reg1_raddr_i,
	input wire [4:0]  reg2_raddr_i,
	//to id
	output reg [63:0] reg1_rdata_o,
	output reg [63:0] reg2_rdata_o,
	//from wb
	input wire [4 :0] reg_waddr_i ,
	input wire [63:0] reg_wdata_i ,
	input wire        reg_wen
);

	reg [63:0] regs[31:0];
	
	integer i;
	
	always @(*)
		begin
			if(rst == 1'b1)
				reg1_rdata_o = 64'b0;
			else if(reg1_raddr_i == 5'b0)
				reg1_rdata_o = 64'b0;
			else if(reg_wen && reg1_raddr_i == reg_waddr_i)
				reg1_rdata_o = reg_wdata_i;
			else 
				reg1_rdata_o = regs[reg1_raddr_i];
		end
		
	always @(*)
		begin
			if(rst == 1'b1)
				reg2_rdata_o = 64'b0;
			else if(reg2_raddr_i == 5'b0)
				reg2_rdata_o = 64'b0;
			else if(reg_wen && reg2_raddr_i == reg_waddr_i)
				reg2_rdata_o = reg_wdata_i;
			else 
				reg2_rdata_o = regs[reg2_raddr_i];
		end
		
	always @(posedge clk)
		begin
			if(rst == 1'b1) begin
				for(i=0;i<32;i=i+1) begin
					regs[i] <= 64'b0;
				end
			end
			else if(reg_wen && reg_waddr_i != 5'b0) begin
				regs[reg_waddr_i] <= reg_wdata_i;
			end
		end

endmodule
module PC
(
	input  wire        clk           ,
	input  wire        rst           ,
	input  wire [63:0] jump_addr_i   ,
	input  wire        jump_en       ,
	input  wire [1 :0] hold_flag_i   ,//流水线暂停标志
	//to if
	output wire [63:0] inst_addr_o
);

	reg [63:0] pc_o;

	always @(posedge clk)
		begin
			if(rst == 1'b1) 
				pc_o <= 64'h0000_0000_0000_0000;
			else if(jump_en)
				pc_o <= jump_addr_i;
			else if(hold_flag_i == 2'b01 || hold_flag_i == 2'b10) 
				pc_o <= pc_o;
			else
				pc_o <= pc_o + 64'd4;
		end

	DFF_SET 
	#
	(
		.DW(64)
	) 
	dff1
	(
		.clk        (clk          ),
		.rst        (rst          ),
		.hold_flag_i(hold_flag_i  ),
		.set_data   (64'b0        ),
	    .data_i     (pc_o         ),
        .data_o     (inst_addr_o  )
	);

endmodule
module REGS
(
	input wire        clk         ,
	input wire        rst         ,
	//from id         
	input wire [4:0]  reg1_raddr_i,
	input wire [4:0]  reg2_raddr_i,
	//to id
	output reg [63:0] reg1_rdata_o,
	output reg [63:0] reg2_rdata_o,
	//from wb
	input wire [4 :0] reg_waddr_i ,
	input wire [63:0] reg_wdata_i ,
	input wire        reg_wen
);
	
	reg [63:0] regs[31:0];
	
	integer i;
	
	always @(*)
		begin
			if(rst == 1'b1)
				reg1_rdata_o = 64'b0;
			else if(reg1_raddr_i == 5'b0)
				reg1_rdata_o = 64'b0;
			else if(reg_wen && reg1_raddr_i == reg_waddr_i)
				reg1_rdata_o = reg_wdata_i;
			else 
				reg1_rdata_o = regs[reg1_raddr_i];
		end
		
	always @(*)
		begin
			if(rst == 1'b1)
				reg2_rdata_o = 64'b0;
			else if(reg2_raddr_i == 5'b0)
				reg2_rdata_o = 64'b0;
			else if(reg_wen && reg2_raddr_i == reg_waddr_i)
				reg2_rdata_o = reg_wdata_i;
			else 
				reg2_rdata_o = regs[reg2_raddr_i];
		end
		
	always @(posedge clk)
		begin
			if(rst == 1'b1) begin
				for(i=0;i<32;i=i+1) begin
					regs[i] <= 64'b0;
				end
			end
			else if(reg_wen && reg_waddr_i != 5'b0) begin
				regs[reg_waddr_i] <= reg_wdata_i;
			end
		end

endmodule
module tb ();

  // Dump the signals to a VCD file. You can view it with gtkwave.
  initial begin
    $dumpfile("tb.vcd");
    $dumpvars(0, tb);
    #1;
  end

  // Wire up the inputs and outputs:
  reg clk;
  reg rst_n;
  reg ena;
  reg [7:0] ui_in;
  reg [7:0] uio_in;
  wire [7:0] uo_out;
  wire [7:0] uio_out;
  wire [7:0] uio_oe;

  // Replace tt_um_example with your module name:
  tt_um_rejunity_z80 user_project (

      // Include power ports for the Gate Level test:
`ifdef GL_TEST
      .VPWR(1'b1),
      .VGND(1'b0),
`endif

      .ui_in  (ui_in),    // Dedicated inputs
      .uo_out (uo_out),   // Dedicated outputs
      .uio_in (uio_in),   // IOs: Input path
      .uio_out(uio_out),  // IOs: Output path
      .uio_oe (uio_oe),   // IOs: Enable path (active high: 0=input, 1=output)
      .ena    (ena),      // enable - goes high when design is selected
      .clk    (clk),      // clock
      .rst_n  (rst_n)     // not reset
  );

endmodule
module tt_um_rejunity_z80 (
    input  wire [7:0] ui_in,    // Dedicated inputs
    output wire [7:0] uo_out,   // Dedicated outputs
    input  wire [7:0] uio_in,   // IOs: Input path
    output wire [7:0] uio_out,  // IOs: Output path
    output wire [7:0] uio_oe,   // IOs: Enable path (active high: 0=input, 1=output)
    input  wire       ena,      // will go high when the design is enabled
    input  wire       clk,      // clock
    input  wire       rst_n     // reset_n - low to reset
);

    // We have to multiplex the 16 bits of (A) address bus and 8 control signals into
    // the 8 output pins that are available in TinyTapeout.
    wire  [7:0] ctrl_signals;
    wire [15:0] addr_bus;

    // Use mux_control to select between the address bus and control signals
    //   [00] --- {A0 - A7} 
    //   [01] --- {A8 - A15}
    //   [1?] --- control signals {m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n}

    // reg [1:0] clk_counter;
    // always @(posedge clk)
    //     clk_counter <= (rst_n) ? clk_counter + 1 : 0;
    // wire z80_clk = (rst_n) ? clk_counter[1:0] == 0: clk; // Z80 clock is pulsed once every 4 TinyTapeout clock cycles

    // assign uo_out = (clk_counter[0] == 0) ? ctrl_signals :
    //                 (clk_counter[1] == 0) ? addr_bus[7:0] :
    //                                         addr_bus[15:8];

    wire z80_clk = clk;
    wire [1:0] mux_control = ui_in[7:6];
    assign uo_out = (mux_control[1] == 1) ? ctrl_signals :
                    (mux_control[0] == 0) ? addr_bus[7:0] :
                                            addr_bus[15:8];

    // reg [7:0] mux_out;
    // assign uo_out = mux_out;
    // always @(*) begin
    //     case(ui_in[7:6])
    //         2'd0:  mux_out = addr_bus[7:0];
    //         2'd1:  mux_out = addr_bus[15:8];
    //         2'd2:  mux_out = ctrl_signals;
    //         2'd3:  mux_out = ctrl_signals;
    //     endcase
    // end
    
    wire doe; // Data Output Enable
    assign uio_oe  = {8{doe}}; // (active high: 0=input, 1=output)

    z80 z80 (
        .clk     (z80_clk),
        .cen     (ena),
        .reset_n (rst_n),
        .wait_n  (ui_in[0]),
        .int_n   (ui_in[1]),
        .nmi_n   (ui_in[2]),
        .busrq_n (ui_in[3]),
        .di      (uio_in),
        .dout    (uio_out),
        .doe     (doe),
        .A       (addr_bus),
        .m1_n    (ctrl_signals[0]),
        .mreq_n  (ctrl_signals[1]),
        .iorq_n  (ctrl_signals[2]),
        .rd_n    (ctrl_signals[3]),
        .wr_n    (ctrl_signals[4]),
        .rfsh_n  (ctrl_signals[5]),
        .halt_n  (ctrl_signals[6]),
        .busak_n (ctrl_signals[7])
    );
endmodule
module z80 (
    input  wire         clk,
    input  wire         cen,
    input  wire         reset_n,
    input  wire         wait_n,
    input  wire         int_n,
    input  wire         nmi_n,
    input  wire         busrq_n,

    input  wire [7:0]   di,
    output wire [7:0]   dout,
    output wire         doe,

    output wire [15:0]  A,
    output wire         m1_n,
    output wire         mreq_n,
    output wire         iorq_n,
    output wire         rd_n,
    output wire         wr_n,
    output wire         rfsh_n,
    output wire         halt_n,
    output wire         busak_n
);

    tv80s #(
        .Mode(0),   // Z80 mode
        .T2Write(1),// wr_n active in T2
        .IOWait(1)  // std I/O cycle
    ) tv80s (
        .reset_n (reset_n),
        .clk (clk),
        .cen (cen),
        .wait_n (wait_n),
        .int_n (int_n),
        .nmi_n (nmi_n),
        .busrq_n (busrq_n),
        .m1_n (m1_n),
        .mreq_n (mreq_n),
        .iorq_n (iorq_n),
        .rd_n (rd_n),
        .wr_n (wr_n),
        .rfsh_n (rfsh_n),
        .halt_n (halt_n),
        .busak_n (busak_n),
        .A (A),
        .di (di),
        .dout (dout),
        .write (doe) 
    );

endmodule
module tv80_reg (/*AUTOARG*/
  // Outputs
  DOBH, DOAL, DOCL, DOBL, DOCH, DOAH,
  // Inputs
  AddrC, AddrA, AddrB, DIH, DIL, clk, CEN, WEH, WEL
  );
    input  [2:0] AddrC;
    output [7:0] DOBH;
    input  [2:0] AddrA;
    input  [2:0] AddrB;
    input  [7:0] DIH;
    output [7:0] DOAL;
    output [7:0] DOCL;
    input  [7:0] DIL;
    output [7:0] DOBL;
    output [7:0] DOCH;
    output [7:0] DOAH;
    input  clk, CEN, WEH, WEL;

  reg [7:0] RegsH [0:7];
  reg [7:0] RegsL [0:7];

  always @(posedge clk)
    begin
      if (CEN)
        begin
          if (WEH) RegsH[AddrA] <= DIH;
          if (WEL) RegsL[AddrA] <= DIL;
        end
    end

  assign DOAH = RegsH[AddrA];
  assign DOAL = RegsL[AddrA];
  assign DOBH = RegsH[AddrB];
  assign DOBL = RegsL[AddrB];
  assign DOCH = RegsH[AddrC];
  assign DOCL = RegsL[AddrC];

  // break out ram bits for waveform debug
// synopsys translate_off
  wire [7:0] B = RegsH[0];
  wire [7:0] C = RegsL[0];
  wire [7:0] D = RegsH[1];
  wire [7:0] E = RegsL[1];
  wire [7:0] H = RegsH[2];
  wire [7:0] L = RegsL[2];

  wire [15:0] IX = { RegsH[3], RegsL[3] };
  wire [15:0] IY = { RegsH[7], RegsL[7] };
// synopsys translate_on

endmodule
module wav_player(
    input CLK,
    input switch_play,
	 output reg audio_out
    );
	 
localparam MEM_SIZE = 3901; // 

reg [7:0] memory[MEM_SIZE-1:0];
initial begin
  $readmemh("01_b3901.txt", memory);
end

wire s_start;
debouncer d1(.CLK (CLK), .switch_input (switch_play), .trans_up (s_start));

reg play = 0;
reg [3:0] prescaler; 
reg [7:0] counter;
reg [19:0] address;
reg [7:0] value;

always @(posedge CLK)
begin
  if (play)
  begin
    prescaler <= prescaler + 1;
    if (prescaler == 5)  // 8kHz x 256 steps = 2.048 MHz
    begin
      prescaler <= 0;
	   counter <= counter + 1;
      value <= memory[address];
      audio_out <= (value > counter);
      if (counter == 255)
      begin
        address <= address + 1;
        if (address == MEM_SIZE)
        begin
          play <= 0;
			 address <= 0;
        end			 
      end		
    end
  end
  if (s_start)
  begin
    play <= 1;
  end	 
end

endmodule
module debouncer(
    input CLK,
    input switch_input,
    output reg state,
    output trans_up,
    output trans_dn
    );

// Synchronize the switch input to the clock
reg sync_0, sync_1;
always @(posedge CLK) 
begin
  sync_0 = switch_input;
end
	
always @(posedge CLK) 
begin
  sync_1 = sync_0;
end

// Debounce the switch
reg [16:0] count;
wire idle = (state == sync_1);
wire finished = &count;	// true when all bits of count are 1's

always @(posedge CLK)
begin
  if (idle)
  begin
    count <= 0;
  end
  else 
  begin
    count <= count + 16'd1;  
    if (finished)
    begin
      state <= ~state;  
    end
  end
end

assign trans_dn = ~idle & finished & ~state;
assign trans_up = ~idle & finished & state;

endmodule
module tone_tester(
    input CLK,
    output tone_1khz,
    output tone_100hz,
    output tone_12khz
    );

reg [31:0] period_1khz = 1000;
reg [31:0] period_100hz = 10000;
reg [31:0] period_12khz = 80;

tone #(12) t1(.CLK (CLK), .period (period_1khz), .tone_out (tone_1khz));
tone #(12) t2(.CLK (CLK), .period (period_100hz), .tone_out (tone_100hz));
tone #(12) t3(.CLK (CLK), .period (period_12khz), .tone_out (tone_12khz));

endmodule
module tone(
    input CLK,
    input[31:0] period, // microseconds 
    output reg tone_out
    );

parameter CLK_F = 32; // CLK freq in MHz

reg [5:0] prescaler = 0; 
reg [31:0] counter = 0;

always @(posedge CLK)
begin
  prescaler <= prescaler + 1;
  if (prescaler == CLK_F / 2 - 1) 
  begin
    prescaler <= 0;
    counter <= counter + 1;
    if (counter == period - 1)
    begin
      counter <= 0;
      tone_out <= ~ tone_out;
    end		
  end  
end

endmodule
module vga(
    input CLK,  // Papilio 32MHz
    output HS, VS,
    output [9:0] x,
    output reg [9:0] y,
    output blank
    );

reg [9:0] xc;
 
// Horizontal 640 + fp 16 + HS 96 + bp 48 = 800 pixel clocks
// Vertical, 480 + fp 11 lines + VS 2 lines + bp 31 lines = 524 lines
assign blank = ((xc < 160) | (xc > 800) | (y > 479));
assign HS = ~ ((xc > 16) & (xc < 112));
assign VS = ~ ((y > 491) & (y < 494));
assign x = ((xc < 160)?0:(xc - 160));

always @(posedge CLK)
begin
  if (xc == 800)
  begin
    xc <= 0;
    y <= y + 1;
  end
  else begin
    xc <= xc + 2;
  end
  if (y == 524)
  begin
    y <= 0; 
  end
end

endmodule
module vga_game(
    input CLK,
    input up_switch,
    input dn_switch,
    input left_switch,
    input right_switch,
    output HS,
    output VS,
    output [2:0] RED,
    output [2:0] GREEN,
    output [1:0] BLUE
    );

wire [9:0] x, y;
wire blank;
reg [15:0] prescaler;

vga v(.CLK (CLK), .HS (HS), .VS (VS), .x (x), .y (y), .blank (blank));

reg [9:0] o_x = 320;
reg [9:0] o_y = 240;
wire object = x>o_x & x<o_x+30 & y>o_y & y<o_y+30;

wire border = (x>0 & x<10) | (x>630 & x<640) | (y>0 & y<10) | (y>470 & y<480);

assign RED = (border & ~ blank)?7:0;
assign GREEN = ((border | object) & ~ blank)?7:0;
assign BLUE = (border & ~ blank)?3:0;

always @(posedge CLK)
begin
  prescaler <= prescaler + 1;
  if (prescaler == 0)
  begin
    if (~ up_switch)
    begin
      o_y <= o_y - 1;
    end
    if (~ dn_switch)
    begin
      o_y <= o_y + 1;
    end
    if (~ left_switch)
    begin
      o_x <= o_x - 1;
    end
    if (~ right_switch)
    begin
      o_x <= o_x + 1;
    end
  end
end

endmodule
module vga_basic(
    input CLK,
    output HS,
    output VS,
    output [2:0] RED,
    output [2:0] GREEN,
    output [1:0] BLUE
    );

wire [9:0] x, y;

vga v(.CLK (CLK), .HS (HS), .VS (VS), .x (x), .y (y));

assign RED = ((x > 0) & (x < 300) & (y > 0) & (y < 300))?7:0;
assign GREEN = ((x > 200) & (x < 400) & (y > 150) & (y < 350)?7:0);
assign BLUE = ((x > 300) & (x < 600) & (y > 180) & (y < 480))?3:0;

endmodule
module data_selector(
    input A,
    input B,
    input SEL,
    output reg Q
    );

always @(A or B or SEL)
begin
	if (SEL) 
		Q = A;
	else
		Q = B;
end

endmodule
module timer(
    input CLK,
    input switch_up,
    input switch_dn,
    input switch_cancel,
    input switch_start_stop,
    output [7:0] SEG,
    output [3:0] DIGIT,
    output BUZZER
    );
	 
wire s_up, s_dn, s_cancel, s_start_stop;
debouncer d1(.CLK (CLK), .switch_input (switch_up), .trans_up (s_up));
debouncer d2(.CLK (CLK), .switch_input (switch_dn), .trans_up (s_dn));
debouncer d3(.CLK (CLK), .switch_input (switch_cancel), .trans_up (s_cancel));
debouncer d4(.CLK (CLK), .switch_input (switch_start_stop), .trans_up (s_start_stop));

reg alarm_on = 0;
alarm a(.CLK (CLK), .BUZZER (BUZZER), .enable (alarm_on));

reg [3:0] secs = 0;
reg [3:0] ten_secs = 0;
reg [3:0] mins = 1;
reg [3:0] mins_stored;
reg [25:0] prescaler = 0;

display_7_seg display(.CLK (CLK), 
		.units (secs), .tens (ten_secs), .hundreds (mins),
		.SEG (SEG), .DIGIT (DIGIT));

// States
localparam SETTING = 0, RUNNING = 1, BEEPING = 2;
reg [1:0] state = SETTING; 

always @(posedge CLK) 
begin
  case (state)
    SETTING : begin
      handle_settings();
      if (s_start_stop)
      begin
        mins_stored <= mins;
        state <= RUNNING;
      end
    end
    RUNNING : begin
      decrement_time();
      if (s_start_stop)
      begin
        state <= SETTING;
      end
      if (s_cancel)
      begin
        reset_time();
        state <= SETTING;
      end
      if ((secs == 0) & (ten_secs == 0) & (mins == 0))
      begin
        alarm_on <= 1;
        state <= BEEPING;
      end
    end
    BEEPING : begin
      if (s_cancel)
      begin
        alarm_on <= 0;
        state <= SETTING;
        reset_time();
		end
	 end
  endcase
end

task handle_settings;
begin
  if (s_up)
  begin
    mins <= mins + 1;
    if (mins == 9)
    begin
      mins <= 1;
    end
  end
  if (s_dn)
  begin
	 mins <= mins - 1;
    if (mins == 1)
    begin
      mins <= 9;
    end
  end
end
endtask

task decrement_time;
begin
  prescaler <= prescaler + 1;
  if (prescaler == 26'd11999999) // 12 MHz to 1Hz
  begin
    prescaler <= 0;
    secs <= secs - 1;
    if (secs < 1)
    begin
      secs <= 9;
      ten_secs <= ten_secs - 1;
      if (ten_secs < 1)
      begin
        ten_secs <= 5;
        mins <= mins - 1;
      end
    end
  end
end
endtask


task reset_time;
begin
  secs <= 0;
  ten_secs <= 0;
  mins <= mins_stored;
end
endtask

endmodule
module decoder_7_seg(
	input CLK,
   input [3:0] D,
   output reg [7:0] SEG
   );

always @(posedge CLK) 
begin
	case(D)
    4'd0: SEG <= 8'b00000011;
    4'd1: SEG <= 8'b10011111; 
    4'd2: SEG <= 8'b00100101;
    4'd3: SEG <= 8'b00001101;
    4'd4: SEG <= 8'b10011001;
    4'd5: SEG <= 8'b01001001;
    4'd6: SEG <= 8'b01000001;
    4'd7: SEG <= 8'b00011111;
    4'd8: SEG <= 8'b00000001;
    4'd9: SEG <= 8'b00001001;
    default: SEG <= 8'b11111111;
	endcase
end

endmodule
module alarm(
    input CLK,
    input enable,
    output reg BUZZER
    );

reg [25:0] count;

always @(posedge CLK) 
begin
  count <= count + 1;
  if ((count == 26'd11999) & enable) // 1kHz
  begin
    BUZZER <= ~ BUZZER;
    count <= 0;
  end
end

endmodule
module counter(
    input Clock,
    output reg [3:0] Q
    );
	 
always @(posedge Clock)
begin
	Q <= Q + 1;
end

endmodule
module seg_test(
   input CLK,
   input [3:0] D,
   output [7:0] SEG,
   output [2:0]DIGIT
   );	
	
assign DIGIT = 3'b110;

decoder_7_seg decoder(.CLK (CLK), .SEG	(SEG), .D (D));  

endmodule
module vga_mem(
    input CLK,
    output HS,
    output VS,
    output [2:0] RED,
    output [2:0] GREEN,
    output [1:0] BLUE
    );

wire [9:0] x, y;

reg [7:0] mem[4799:0]; // 80 x 60 (8x8 pixels on 640x480)
wire [12:0] mem_index;
wire [7:0] color;

initial begin
  $readmemh("flag.txt", mem);
end

vga v(.CLK (CLK), .HS (HS), .VS (VS), .x (cx), .y (y), .blank (blank));

assign mem_index = (y / 8) * 80 + x / 8; // divide y first to lose LSBs
assign color = mem[mem_index];
assign RED = (blank?0:color[7:5]);
assign GREEN = (blank?0:color[4:2]);
assign BLUE = (blank?0:color[1:0]);

endmodule
module debounce(
    input CLK,
    input switch_a,
    input switch_b,
    output reg led_a,
    output reg led_b,
    output reg led_c
    );

wire s_a_dn, s_b_up, s_a_state;
debouncer d1(.CLK (CLK), .switch_input (switch_a), .trans_dn (s_a_dn));
debouncer d2(.CLK (CLK), .switch_input (switch_b), .trans_up (s_b_up));
debouncer d3(.CLK (CLK), .switch_input (switch_a), .state (s_a_state));

always @(posedge CLK)
begin
  if (s_a_dn)
  begin
    led_a <= ~ led_a;
  end
  if (s_b_up)
  begin
    led_b <= ~ led_b;
  end
  led_c <= s_a_state;
end

endmodule
module alarm(
    input CLK,
    input enable,
    output reg BUZZER
    );

reg [25:0] count;

always @(posedge CLK) 
begin
  count <= count + 1;
  if ((count == 26'd12000) & enable) // 1kHz
  begin
    BUZZER <= ~ BUZZER;
    count <= 0;
  end
end

endmodule
module pwm(
    input pwm_clk,
    input [7:0] duty,
    output reg PWM_PIN
    );

reg [7:0] count = 0;

always @(posedge pwm_clk)
begin
  count <= count + 1;
  PWM_PIN <= (count < duty);
end

endmodule
module pwm_tester(
    input CLK,
    input switch_up,
    input switch_dn,
    output PWM_PIN
    );

wire s_up, s_dn;
debouncer d1(.CLK (CLK), .switch_input (switch_up), .trans_up (s_up));
debouncer d2(.CLK (CLK), .switch_input (switch_dn), .trans_up (s_dn));

reg [7:0] duty = 0;
reg [6:0] prescaler = 0; // CLK freq / 128 / 256 = 1.5kHz
pwm p(.pwm_clk (prescaler[6]), .duty (duty), .PWM_PIN (PWM_PIN));

always @(posedge CLK)
begin
  prescaler <= prescaler + 1;
  if (s_up)
  begin
    duty <= duty + 5;
  end
  if (s_dn)
  begin
    duty <= duty - 5;
  end  
end

endmodule
module servo(
    input CLK,
    input [15:0] pulse_len,  // microseconds
    output reg CONTROL_PIN
    );
	 
parameter CLK_F = 50; // CLK freq in MHz

reg [15:0] prescaler;
reg [15:0] count = 0;

always @(posedge CLK)
begin
  prescaler <= prescaler + 1;
  if (prescaler == CLK_F - 1) 
  begin
    prescaler <= 0;
    count <= count + 1;
    CONTROL_PIN <= (count < pulse_len);
	 if (count == 19999) // 20 milliseconds
    begin
        count <= 0;
    end
  end
end

endmodule
module servo_tester(
    input CLK,
    input switch_up,
    input switch_dn,
    output CONTROL_PIN
    );

wire s_up, s_dn;
debouncer d1(.CLK (CLK), .switch_input (switch_up), .trans_up (s_up));
debouncer d2(.CLK (CLK), .switch_input (switch_dn), .trans_up (s_dn));

reg [15:0] pulse_len = 500; // microseconds

servo #(12) p(.CLK (CLK), .pulse_len (pulse_len), .CONTROL_PIN (CONTROL_PIN));

always @(posedge CLK)
begin
  if (s_up)
  begin
    pulse_len <= pulse_len + 100;
  end
  if (s_dn)
  begin
    pulse_len <= pulse_len - 100;
  end  
end

endmodule
module wav_player(
    input CLK,
    input switch_play,
	 output reg audio_out
    );

localparam MEM_SIZE = 36130; // 

reg [7:0] memory[MEM_SIZE-1:0];
initial begin
  $readmemh("01_05_b36130.txt", memory);

end

wire s_start;
debouncer d1(.CLK (CLK), .switch_input (switch_play), .trans_up (s_start));

reg play = 0;
reg [5:0] prescaler; 
reg [7:0] counter;
reg [19:0] address;
reg [7:0] value;

always @(posedge CLK)
begin
  if (play)
  begin
    prescaler <= prescaler + 1;
    if (prescaler == 24)  // 8kHz x 256 steps = 2.048 MHz
    begin
      prescaler <= 0;
      counter <= counter + 1;
      value <= memory[address];
      audio_out <= (value > counter);
      if (counter == 255)
      begin
        address <= address + 1;
        if (address == MEM_SIZE)
        begin
          play <= 0;
          address <= 0;
        end			 
      end		
    end
  end
  if (s_start)
  begin
    play <= 1;
  end	 
end


endmodule
module tone_tester(
    input CLK,
    output tone_1khz,
    output tone_100hz,
    output tone_12khz
    );

reg [31:0] period_1khz = 1000;
reg [31:0] period_100hz = 10000;
reg [31:0] period_12khz = 80;

tone #(50) t1(.CLK (CLK), .period (period_1khz), .tone_out (tone_1khz));
tone #(50) t2(.CLK (CLK), .period (period_100hz), .tone_out (tone_100hz));
tone #(50) t3(.CLK (CLK), .period (period_12khz), .tone_out (tone_12khz));

endmodule
module timer(
    input CLK,
    input switch_up,
    input switch_dn,
    input switch_cancel,
    input switch_start_stop,
    output [7:0] SEG,
    output [3:0] DIGIT,
    output BUZZER
    );
	 
wire s_up, s_dn, s_cancel, s_start_stop;
debouncer d1(.CLK (CLK), .switch_input (switch_up), .trans_dn (s_up));
debouncer d2(.CLK (CLK), .switch_input (switch_dn), .trans_dn (s_dn));
debouncer d3(.CLK (CLK), .switch_input (switch_cancel), .trans_dn (s_cancel));
debouncer d4(.CLK (CLK), .switch_input (switch_start_stop), .trans_dn (s_start_stop));

reg alarm_on = 0;
alarm a(.CLK (CLK), .BUZZER (BUZZER), .enable (alarm_on));

reg [3:0] secs = 0;
reg [3:0] ten_secs = 0;
reg [3:0] mins = 1;
reg [3:0] mins_stored;
reg [3:0] unused_digit = 4'd10; // digits above 9 not displayed
reg [25:0] prescaler = 0;

display_7_seg display(.CLK (CLK), 
		.units (secs), .tens (ten_secs), .hundreds (mins), .thousands (unused_digit),
		.SEG (SEG), .DIGIT (DIGIT));

// States
localparam SETTING = 0, RUNNING = 1, BEEPING = 2;
reg [1:0] state = SETTING; 

always @(posedge CLK) 
begin
  case (state)
    SETTING : begin
      handle_settings();
      if (s_start_stop)
      begin
        mins_stored <= mins;
        state <= RUNNING;
      end
    end
    RUNNING : begin
      decrement_time();
      if (s_start_stop)
      begin
        state <= SETTING;
      end
      if (s_cancel)
      begin
        reset_time();
        state <= SETTING;
      end
      if ((secs == 0) & (ten_secs == 0) & (mins == 0))
      begin
        alarm_on <= 1;
        state <= BEEPING;
      end
    end
    BEEPING : begin
      if (s_cancel)
      begin
        alarm_on <= 0;
        state <= SETTING;
        reset_time();
		end
	 end
  endcase
end

task handle_settings;
begin
  if (s_up)
  begin
    mins <= mins + 1;
    if (mins == 9)
    begin
      mins <= 1;
    end
  end
  if (s_dn)
  begin
	 mins <= mins - 1;
    if (mins == 1)
    begin
      mins <= 9;
    end
  end
end
endtask

task decrement_time;
begin
  prescaler <= prescaler + 1;
  if (prescaler == 26'd49999999) // 50 MHz to 1Hz
  begin
    prescaler <= 0;
    secs <= secs - 1;
    if (secs < 1)
    begin
      secs <= 9;
      ten_secs <= ten_secs - 1;
      if (ten_secs < 1)
      begin
        ten_secs <= 5;
        mins <= mins - 1;
      end
    end
  end
end
endtask


task reset_time;
begin
  secs <= 0;
  ten_secs <= 0;
  mins <= mins_stored;
end
endtask

endmodule
module alarm(
    input CLK,
    input enable,
    output reg BUZZER
    );

reg [25:0] count;

always @(posedge CLK) 
begin
  count <= count + 1;
  if ((count == 26'd49999) & enable) // 1kHz
  begin
    BUZZER <= ~ BUZZER;
    count <= 0;
  end
end

endmodule
module seg_test(
   input CLK,
   input [3:0] D,
   output [7:0] SEG,
   output [3:0] DIGIT
   );	
	
assign DIGIT = 4'b1110;

decoder_7_seg decoder(.CLK (CLK), .SEG	(SEG), .D (D));  

endmodule