reg [7:0] progaddrh, progaddrm, progaddrl;
+ reg [22:0] progaddr;
+
assign cr_nADV = 0; /* Addresses are always valid! :D */
assign cr_nCE = 0; /* The chip is enabled */
assign cr_nLB = 0; /* Lower byte is enabled */
assign cr_DQ = (~cr_nOE) ? 16'bzzzzzzzzzzzzzzzz : {8'b0, datalatch};
assign cr_A = (addrlatch[15:14] == 2'b00) ? /* extrom */ {9'b0,addrlatch[13:0]} :
(addrlatch[15:13] == 3'b101) ? {1'b1, 9'b0, addrlatch[12:0]} :
- (addrlatch == ADDR_PROGDATA) ? {progaddrh[6:0], progaddrm[7:0], progaddrl[7:0]} :
+ (addrlatch == ADDR_PROGDATA) ? progaddr :
23'b0;
reg [7:0] regbuf;
ADDR_PROGADDRH: if (wr) progaddrh <= data;
ADDR_PROGADDRM: if (wr) progaddrm <= data;
ADDR_PROGADDRL: if (wr) progaddrl <= data;
+ ADDR_PROGDATA: if (rd || wr) begin
+ progaddr <= {progaddrh[6:0], progaddrm[7:0], progaddr[7:0]};
+ {progaddrh[6:0], progaddrm[7:0], progaddr[7:0]} <= {progaddrh[6:0], progaddrm[7:0], progaddr[7:0]} + 23'b1;
+ end
endcase
rdlatch <= rd;
wrlatch <= wr;
`define IN_CLK 8388608
`define OUT_CLK 57600
`define CLK_DIV `IN_CLK / `OUT_CLK
-`define MMAP_ADDR 16'hFF50
+`define DATA_ADDR 16'hFF52
+`define STAT_ADDR 16'hFF53
module UART(
input clk,
inout [7:0] data,
output reg serial = 1);
- reg rdlatch = 0;
- wire decode = (addr == `MMAP_ADDR);
+ wire data_decode = (addr == `DATA_ADDR);
+ wire stat_decode = (addr == `STAT_ADDR);
+ reg data_latch = 0;
+ reg stat_latch = 0;
- wire [7:0] odata;
- assign data = rdlatch ? odata : 8'bzzzzzzzz;
-
- reg [7:0] data_stor = 0;
- reg [15:0] clkdiv = 0;
- reg have_data = 0;
- reg [3:0] diqing = 4'b0000;
-
- wire newdata = (wr) && (!have_data) && decode;
+ reg [7:0] tx_data = 0;
+ reg [15:0] tx_clkdiv = 0;
+ reg [3:0] tx_state = 4'b1011; // 1011 is the not busy state.
+ wire tx_busy = tx_state != 4'b1011;
+ wire tx_newdata = (wr) && (!tx_busy) && data_decode;
- assign odata = have_data ? 8'b1 : 8'b0;
+ assign data = (rd && stat_latch) ? (tx_busy ? 8'b1 : 8'b0) :
+ (rd && data_latch) ? (8'b0) :
+ 8'bzzzzzzzz;
- always @ (posedge clk)
+ always @(posedge clk)
begin
- rdlatch <= rd && decode;
+ data_latch <= rd && data_decode;
+ stat_latch <= rd && stat_decode;
/* deal with diqing */
- if(newdata) begin
- data_stor <= data;
- have_data <= 1;
- diqing <= 4'b0000;
- end else if (clkdiv == 0) begin
- diqing <= diqing + 1;
- if (have_data)
- case (diqing)
+ if(tx_newdata) begin
+ tx_data <= data;
+ tx_state <= 4'b0000;
+ end else if (tx_clkdiv == 0) begin
+ tx_state <= tx_state + 1;
+ if (tx_busy)
+ case (tx_state)
4'b0000: serial <= 0;
- 4'b0001: serial <= data_stor[0];
- 4'b0010: serial <= data_stor[1];
- 4'b0011: serial <= data_stor[2];
- 4'b0100: serial <= data_stor[3];
- 4'b0101: serial <= data_stor[4];
- 4'b0110: serial <= data_stor[5];
- 4'b0111: serial <= data_stor[6];
- 4'b1000: serial <= data_stor[7];
+ 4'b0001: serial <= tx_data[0];
+ 4'b0010: serial <= tx_data[1];
+ 4'b0011: serial <= tx_data[2];
+ 4'b0100: serial <= tx_data[3];
+ 4'b0101: serial <= tx_data[4];
+ 4'b0110: serial <= tx_data[5];
+ 4'b0111: serial <= tx_data[6];
+ 4'b1000: serial <= tx_data[7];
4'b1001: serial <= 1;
- 4'b1010: have_data <= 0;
+ 4'b1010: serial <= 1;
default: $stop;
endcase
end
- /* deal with clkdiv */
- if((newdata && !have_data) || clkdiv == `CLK_DIV)
- clkdiv <= 0;
+ if((tx_newdata && !tx_busy) || (tx_clkdiv == `CLK_DIV))
+ tx_clkdiv <= 0;
else
- clkdiv <= clkdiv + 1;
+ tx_clkdiv <= tx_clkdiv + 1;
end
endmodule
SECTION "boot", HOME[$0]
- ld a, $AA
+boot: ld a, $AA
ld [$FF51], A ; Poke the LEDs
+
+ ld sp, $FFFE
+
+ ld hl, signon
+ call puts
; Write a little bit to the RAM
- ld H, $01
- ld L, $00
- ld A, $00
+ ld hl, $0104
+ xor a
ld [HLI], A
ld [HLI], A
ld [HLI], A
ld [HLI], A
ld [HLI], A
- ld a, $55
- ld [$FF51], A ; Poke the LEDs
-
ld A, $FF
ld [HLI], A
ld [HLI], A
ld [HLI], A
ld [HLI], A
- ld H, $00
- ld L, $00
- ld [HL], $01 ; Select the GB boot rom
- rst $00 ; Boot
+ ld c, $51
+.wait: ld a, [c]
+ cp $00
+ jr nz, .wait
+
+ ld h, a
+ ld l, a
+ ld [hl], $01 ; Select the GB boot rom
+
+ ld a, $55
+ ld [c], a
+
+ ld hl, booting
+ call puts
+
+ rst $00 ; Boot
+
+putc:
+ ld c, $53
+ push af
+.waitport:
+ ld a,[c]
+ cp $00
+ jr nz,.waitport
+ pop af
+ ld [$FF52],a
+ ret
+
+puts:
+ ld a, [hli]
+ cp $00
+ ret z
+ call putc
+ jr puts
+
+signon:
+ db $0D,$0A,$1B,"[1mFPGABoy Boot ROM",$1B,"[0m",$0D,$0A,0
+booting:
+ db "Booting...",$0D,$0A,0
+
+
SECTION "a", HOME[$100]
nop ; Make sure we don't overflow.
\ No newline at end of file