Cut 1 at an onboard bootloader
authorJoshua Wise <joshua@rebirth.joshuawise.com>
Wed, 7 May 2008 12:30:04 +0000 (08:30 -0400)
committerJoshua Wise <joshua@rebirth.joshuawise.com>
Wed, 7 May 2008 12:30:04 +0000 (08:30 -0400)
CoreTop.ucf
System.v
Uart.v
fpgaboot.asm

index 1708eeb..1981fcd 100644 (file)
@@ -1,5 +1,6 @@
 NET "xtal" LOC="B8";
 NET "serio"  LOC = "p9";
+NET "serin" LOC = "u6";
 
 NET "leds<0>"  LOC = "j14"  ;
 NET "leds<1>"  LOC = "j15"  ;
index 62683d3..8f9ef08 100644 (file)
--- a/System.v
+++ b/System.v
@@ -202,6 +202,7 @@ module CoreTop(
        input [3:0] buttons,
        output wire [7:0] leds,
        output serio,
+       input serin,
        output wire [3:0] digits,
        output wire [7:0] seven,
        output wire cr_nADV, cr_nCE, cr_nOE, cr_nWE, cr_CRE, cr_nLB, cr_nUB, cr_CLK,
@@ -221,6 +222,7 @@ module CoreTop(
        
        wire [7:0] leds;
        wire serio;
+       wire serin = 1;
        wire [3:0] digits;
        wire [7:0] seven;
        wire [7:0] switches = 8'b0;
@@ -348,7 +350,8 @@ module CoreTop(
                .data(data[0]),
                .wr(wr[0]),
                .rd(rd[0]),
-               .serial(serio)
+               .serial(serio),
+               .serialrx(serin)
                );
 
        InternalRAM ram(
diff --git a/Uart.v b/Uart.v
index e521304..332620b 100644 (file)
--- a/Uart.v
+++ b/Uart.v
@@ -10,7 +10,8 @@ module UART(
        input rd,
        input [15:0] addr,
        inout [7:0] data,
-       output reg serial = 1);
+       output reg serial = 1,
+       input serialrx);
 
        wire data_decode = (addr == `DATA_ADDR);
        wire stat_decode = (addr == `STAT_ADDR);
@@ -19,22 +20,27 @@ module UART(
        
        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;
+       reg [3:0] tx_state = 4'b0000;
+       reg tx_busy = 0;
        wire tx_newdata = (wr) && (!tx_busy) && data_decode;
        
-       assign data = (rd && stat_latch) ? (tx_busy ? 8'b1 : 8'b0) :
-                       (rd && data_latch) ? (8'b0) :
+       reg rx_hasdata = 0;
+       reg [15:0] rx_clkdiv = 0;
+       reg [3:0] rx_state = 4'b0000;
+       reg [7:0] rx_data;
+       
+       assign data = (stat_latch) ? {6'b0, rx_hasdata, tx_busy} :
+                       (data_latch) ? rx_data :
                        8'bzzzzzzzz;
 
        always @(posedge clk)
        begin
                data_latch <= rd && data_decode;
                stat_latch <= rd && stat_decode;
-               /* deal with diqing */
                if(tx_newdata) begin
                        tx_data <= data;
                        tx_state <= 4'b0000;
+                       tx_busy <= 1;
                end else if (tx_clkdiv == 0) begin
                        tx_state <= tx_state + 1;
                        if (tx_busy)
@@ -49,14 +55,44 @@ module UART(
                                4'b0111: serial <= tx_data[6];
                                4'b1000: serial <= tx_data[7];
                                4'b1001: serial <= 1;
-                               4'b1010: serial <= 1;
+                               4'b1010: tx_busy <= 0;
                                default: $stop;
+                               endcase
+               end
+               
+               if ((rx_state == 0) && (serialrx == 0) /*&& (rx_hasdata == 0)*/)                /* Kick off. */
+                       rx_state <= 4'b0001;
+               else if ((rx_state != 4'b0000) && (rx_clkdiv == 0)) begin
+                       if (rx_state != 4'b1010)
+                               rx_state <= rx_state + 1;
+                       else
+                               rx_state <= 0;
+                       case (rx_state)
+                       4'b0001:        begin end /* Twiddle thumbs -- this is the end of the half bit. */
+                       4'b0010:        rx_data[0] <= serialrx;
+                       4'b0011:        rx_data[1] <= serialrx;
+                       4'b0100:        rx_data[2] <= serialrx;
+                       4'b0101:        rx_data[3] <= serialrx;
+                       4'b0110:        rx_data[4] <= serialrx;
+                       4'b0111:        rx_data[5] <= serialrx;
+                       4'b1000:        rx_data[6] <= serialrx;
+                       4'b1001:        rx_data[7] <= serialrx;
+                       4'b1010:        begin end /* Expect a 1 */
                        endcase
                end
+               
+               rx_hasdata <= (rx_hasdata && ~(rd && data_decode)) || ((rx_state == 4'b1010) && (tx_clkdiv == 0));
 
-               if((tx_newdata && !tx_busy) || (tx_clkdiv == `CLK_DIV))
+               if(tx_newdata || (tx_clkdiv == `CLK_DIV))
                        tx_clkdiv <= 0;
                else
                        tx_clkdiv <= tx_clkdiv + 1;
+               
+               if ((rx_state == 0) && (serialrx == 0) /*&& (rx_hasdata == 0)*/)                /* Wait half a period before advancing. */
+                       rx_clkdiv <= `CLK_DIV / 2 + `CLK_DIV / 4;
+               else if (rx_clkdiv == `CLK_DIV)
+                       rx_clkdiv <= 0;
+               else
+                       rx_clkdiv <= rx_clkdiv + 1;
        end
 endmodule
index 4a1089f..0a714b1 100644 (file)
@@ -7,34 +7,22 @@ boot: ld a, $AA
        ld hl, signon
        call puts
        
-       ; Write a little bit to the RAM
-       ld hl, $0104
-       xor a
-       ld [HLI], A
-       ld [HLI], A
-       ld [HLI], A
-       ld [HLI], A
-       ld [HLI], A
-       ld [HLI], A
-       ld [HLI], A
-       ld [HLI], A
+.wait: ld a, [$FF53]
+       and $02
+       jr z, .nodata
+       ld a, [$FF52]
+       ld [$FF51], a
        
-       ld A, $FF
-       ld [HLI], A
-       ld [HLI], A
-       ld [HLI], A
-       ld [HLI], A
-       ld [HLI], A
-       ld [HLI], A
-       ld [HLI], A
-       ld [HLI], A
-       
-       ld c, $51
-       
-.wait: ld a, [c]
+       cp $1B          ; Escape
+       jp z, .cbc
+       ld [$FF52], a
+.cbc:  call z, bootcmd
+
+.nodata:       ld a, [$FF51]
        cp $00
        jr nz, .wait
 
+doboot:        xor a
        ld h, a
        ld l, a
        ld [hl], $01    ; Select the GB boot rom
@@ -47,12 +35,17 @@ boot:       ld a, $AA
        
        rst $00         ; Boot
 
+signon:
+       db $0D,$0A,$1B,"[1mFPGABoy Boot ROM",$1B,"[0m",$0D,$0A,0
+booting:
+       db "Booting...",$0D,$0A,0
+
 putc:
        ld c, $53
        push af
 .waitport:
        ld a,[c]
-       cp $00
+       and $01
        jr nz,.waitport
        pop af
        ld [$FF52],a
@@ -65,12 +58,61 @@ puts:
        call putc
        jr puts
 
-signon:
-       db $0D,$0A,$1B,"[1mFPGABoy Boot ROM",$1B,"[0m",$0D,$0A,0
-booting:
-       db "Booting...",$0D,$0A,0
-
+getc:
+       ld a, [$FF53]
+       and $02
+       jr z, getc
+       ld a, [$FF52]
+       ret
 
+bootcmd:
+       call getc
+       cp $56  ;V
+       jr z,.version
+       cp $41  ;A
+       jr z,.addr
+       cp $44  ;D
+       jr z,.data
+       cp $50  ;P
+       jr z,.prog
+       cp $42  ;B
+       jr z,doboot
+       cp $1B
+       jr z,bootcmd    ; If you keep yelling, you're bound to get the thing's attention.
+       ld a, $3f       ;?
+       jr putc
+.version:
+       ld hl, .verstr
+       jr puts
+.verstr:
+       db "V1.00",0
+.addr:
+       call getc
+       ld [$FF60], A
+       call getc
+       ld [$FF61], A
+       call getc
+       ld [$FF62], A
+       ld A, $41       ;A
+       jr putc
+.data:
+       call getc       ; byte count
+       ld c, a
+.dl:   call getc
+       ld [$FF63], A
+       dec c
+       jp nz, .dl
+       ld A, $44       ;D
+       ret
+.prog:
+       ld hl, $FF80
+       ld c, $7F
+.pl:   dec c
+       jp z, $FF80
+       call getc
+       ld [hli], a
+       jr .pl
+       
        SECTION "a", HOME[$100]
        nop     ; Make sure we don't overflow.
        
\ No newline at end of file
This page took 0.03329 seconds and 4 git commands to generate.