From 298e8085b4f8f70121204fa4aed3a188034f6879 Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Wed, 7 May 2008 08:30:04 -0400 Subject: [PATCH] Cut 1 at an onboard bootloader --- CoreTop.ucf | 1 + System.v | 5 ++- Uart.v | 52 ++++++++++++++++++++++---- fpgaboot.asm | 102 ++++++++++++++++++++++++++++++++++++--------------- 4 files changed, 121 insertions(+), 39 deletions(-) diff --git a/CoreTop.ucf b/CoreTop.ucf index 1708eeb..1981fcd 100644 --- a/CoreTop.ucf +++ b/CoreTop.ucf @@ -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" ; diff --git a/System.v b/System.v index 62683d3..8f9ef08 100644 --- 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 --- 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 diff --git a/fpgaboot.asm b/fpgaboot.asm index 4a1089f..0a714b1 100644 --- a/fpgaboot.asm +++ b/fpgaboot.asm @@ -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 -- 2.39.2