--- /dev/null
+`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,
+ 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 = 0;
+ wire [7:0] imasked = ihold & imask;
+
+ assign data = rd ?
+ (addr == `ADDR_IF) ? ihold :
+ (addr == `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 @ (negedge clk)
+ begin
+ if (wr) begin
+ case(addr)
+ `ADDR_IF : ihold <= iflag | data;
+ `ADDR_IE : imask <= data;
+ endcase
+
+ end
+ else
+ ihold <= ihold | iflag;
+ end
+
+endmodule
output wire [3:0] digits,
output wire [7:0] seven);
- wire clk;
- //IBUFG ibuf (.O(clk), .I(iclk));
-
+ wire clk;
CPUDCM dcm (.CLKIN_IN(xtal), .CLKFX_OUT(clk));
wire [15:0] addr;
.switches(switches)
);
- UART nouart (
+ UART nouart ( /* no u */
.clk(clk),
.wr(wr),
.rd(rd),
.clk(clk),
.wr(wr),
.rd(rd));
+
+ wire irq, tmrirq;
+ wire [7:0] jaddr;
+ Timer tmr(
+ .clk(clk),
+ .wr(wr),
+ .rd(rd),
+ .addr(addr),
+ .data(data),
+ .irq(tmrirq));
+
+ Interrupt intr(
+ .clk(clk),
+ .rd(rd),
+ .wr(wr),
+ .addr(addr),
+ .data(data),
+ .vblank(0),
+ .lcdc(0),
+ .tovf(tmrirq),
+ .serial(0),
+ .buttons(0),
+ .master(irq),
+ .jaddr(jaddr));
endmodule
module TestBench();
.rd(rd),
.serial(serio));
+ wire irq, tmrirq;
+ wire [7:0] jaddr;
+ Timer tmr(
+ .clk(clk),
+ .wr(wr),
+ .rd(rd),
+ .addr(addr),
+ .data(data),
+ .irq(tmrirq));
+
+ Interrupt intr(
+ .clk(clk),
+ .rd(rd),
+ .wr(wr),
+ .addr(addr),
+ .data(data),
+ .vblank(0),
+ .lcdc(0),
+ .tovf(tmrirq),
+ .serial(0),
+ .buttons(0),
+ .master(irq),
+ .jaddr(jaddr));
+
// Switches sw(
// .clk(clk),
// .address(addr),
--- /dev/null
+`define ADDR_DIV 16'hFF04
+`define ADDR_TIMA 16'hFF05
+`define ADDR_TMA 16'hFF06
+`define ADDR_TAC 16'hFF07
+
+module Timer(
+ input clk,
+ input wr,
+ input rd,
+ input [15:0] addr,
+ inout [7:0] data,
+ output reg irq);
+
+ reg [7:0] tima = 0, tma = 0, tac = 0, div = 0;
+ reg ovf = 0;
+ reg [9:0] clkdv;
+
+ wire is_tima = addr == `ADDR_TIMA;
+ wire is_tma = addr == `ADDR_TMA;
+ wire is_tac = addr == `ADDR_TAC;
+
+ assign data = rd ?
+ is_tima ? tima :
+ is_tma ? tma :
+ is_tac ? tac :
+ 8'bzzzzzzzz :
+ 8'bzzzzzzzz;
+
+ wire cksel = tac[2] ?
+ (tac[1:0] == 2'b00) ? (clkdv == 10'b0) :
+ (tac[1:0] == 2'b01) ? (clkdv[3:0] == 4'b0) :
+ (tac[1:0] == 2'b10) ? (clkdv[5:0] == 6'b0) :
+ (clkdv[7:0] == 8'b0) :
+ 0;
+
+ always @ (negedge clk)
+ begin
+ if(wr) begin
+ case(addr)
+ `ADDR_DIV: div <= 8'b0;
+ `ADDR_TIMA: tima <= data;
+ `ADDR_TMA: tma <= data;
+ `ADDR_TAC: tac <= data;
+ endcase
+ end
+ else begin
+ if(ovf) begin
+ tima <= tma;
+ ovf <= 0;
+ irq <= 1;
+ end
+ else begin
+ if(cksel)
+ {ovf,tima} <= {1'b0,tima} + 1;
+ if(irq)
+ irq <= 0;
+ end
+
+ if(clkdv[7:0] == 8'b0)
+ div <= div + 1;
+ end
+ clkdv <= clkdv + 1;
+ end
+
+endmodule
ld hl,waitswstr
call puts
+ ld c, $07
+ ld a, $07 ;start timer, 4.096KHz
+ ld [c], a
+
ld c, $51
ld a, $00
ld [c],a
+.loop1:
+ push bc
+ call testa
+ pop bc
ld c, $51
ld b, $0
-.loop1:
ld a,[c]
cp b
jr z,.loop1
ret
waitswstr:
- db "Diagnostic ROM complete; flip switches to nonzero and then to zero to reset.",$0D,$0A,0
+ db "Diagnostic ROM complete; flip switches to nonzero and then to zero to reset. Expect A.",$0D,$0A,0
+
+testa:
+ ld c, $0F
+ ld a, [c]
+ ld b, $00
+ cp b
+ ret z
+ xor a
+ ld [c], a
+ ld hl, $D000
+ ld c, [hl]
+ inc bc
+ ld [hl], c
+ ld a, c
+ ld c, $50
+ ld [c], a
+ ret
; Core instruction basic acceptance tests.
insntest:
; Serial port manipulation functions.
putc:
- push af
ld b, 0
ld c, $50
.waitport:
ld a,[c]
cp b
jr nz,.waitport
- pop af
ld [c],a
ret