`define ADDR_IF 16'hFF0F `define ADDR_IE 16'hFFFF module Interrupt( input clk, input rd, input wr, input [15:0] addr, inout [7:0] data, input vblank, input lcdc, input tovf, input serial, input buttons, output master, input ack, output [7:0] jaddr); wire [7:0] iflag = {3'b0,buttons,serial,tovf,lcdc,vblank}; reg [7:0] imask = 16'hFFFF; reg [7:0] ihold = 8'b0; wire [7:0] imasked = ihold & imask; reg rdlatch = 0; reg [15:0] addrlatch = 0; assign data = rdlatch ? (addrlatch == `ADDR_IF) ? ihold : (addrlatch == `ADDR_IE) ? imask : 8'bzzzzzzzz : 8'bzzzzzzzz; assign master = (imasked) != 0; assign jaddr = imasked[0] ? 8'h40 : imasked[1] ? 8'h48 : imasked[2] ? 8'h50 : imasked[3] ? 8'h58 : imasked[4] ? 8'h60 : 8'h00; always @(posedge clk) begin if (wr && (addr == `ADDR_IF || addr == `ADDR_IE)) begin case(addr) `ADDR_IF : ihold <= iflag | data; `ADDR_IE : begin imask <= data; ihold <= ihold | iflag; end endcase end else if (ack) ihold <= ihold & (imasked[0] ? 8'b11111110 : imasked[1] ? 8'b11111101 : imasked[2] ? 8'b11111011 : imasked[3] ? 8'b11110111 : imasked[4] ? 8'b11101111 : 8'b11111111); else ihold <= ihold | iflag; rdlatch <= rd; addrlatch <= addr; end endmodule