From: Joshua Wise Date: Tue, 6 May 2008 10:29:22 +0000 (-0400) Subject: Peripherals now have internal latches. X-Git-Url: http://git.joshuawise.com/fpgaboy.git/commitdiff_plain/a8f4468d0cd6910eba8031e21038d76857a2c107?hp=74610a872e3bead82589e6ea786e928f319540e4 Peripherals now have internal latches. --- diff --git a/Interrupt.v b/Interrupt.v index fcc396b..2686146 100644 --- a/Interrupt.v +++ b/Interrupt.v @@ -19,10 +19,13 @@ module Interrupt( 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 = rd ? - (addr == `ADDR_IF) ? ihold : - (addr == `ADDR_IE) ? imask : + assign data = rdlatch ? + (addrlatch == `ADDR_IF) ? ihold : + (addrlatch == `ADDR_IE) ? imask : 8'bzzzzzzzz : 8'bzzzzzzzz; @@ -45,6 +48,8 @@ module Interrupt( end else ihold <= ihold | iflag; + rdlatch <= rd; + addrlatch <= addr; end endmodule diff --git a/LCDC.v b/LCDC.v index a198c45..add6893 100644 --- a/LCDC.v +++ b/LCDC.v @@ -21,6 +21,10 @@ module LCDC( output wire lcdclk, lcdvs, lcdhs, output reg [2:0] lcdr, lcdg, output reg [1:0] lcdb); + /***** Bus latches *****/ + reg rdlatch = 0; + reg [15:0] addrlatch = 0; + /***** Needed prototypes *****/ wire [1:0] pixdata; @@ -172,26 +176,28 @@ module LCDC( end /***** Bus interface *****/ - assign data = rd ? - ((addr == `ADDR_LCDC) ? rLCDC : - (addr == `ADDR_STAT) ? {rSTAT[7:3], (rLYC == posy) ? 1'b1 : 1'b0, mode} : - (addr == `ADDR_SCY) ? rSCY : - (addr == `ADDR_SCX) ? rSCX : - (addr == `ADDR_LY) ? posy : - (addr == `ADDR_LYC) ? rLYC : - (addr == `ADDR_BGP) ? rBGP : - (addr == `ADDR_OBP0) ? rOBP0 : - (addr == `ADDR_OBP1) ? rOBP1 : - (addr == `ADDR_WY) ? rWY : - (addr == `ADDR_WX) ? rWX : - (decode_tiledata && addr[0]) ? tilehigh : - (decode_tiledata && ~addr[0]) ? tilelow : + assign data = rdlatch ? + ((addrlatch == `ADDR_LCDC) ? rLCDC : + (addrlatch == `ADDR_STAT) ? {rSTAT[7:3], (rLYC == posy) ? 1'b1 : 1'b0, mode} : + (addrlatch == `ADDR_SCY) ? rSCY : + (addrlatch == `ADDR_SCX) ? rSCX : + (addrlatch == `ADDR_LY) ? posy : + (addrlatch == `ADDR_LYC) ? rLYC : + (addrlatch == `ADDR_BGP) ? rBGP : + (addrlatch == `ADDR_OBP0) ? rOBP0 : + (addrlatch == `ADDR_OBP1) ? rOBP1 : + (addrlatch == `ADDR_WY) ? rWY : + (addrlatch == `ADDR_WX) ? rWX : + (decode_tiledata && addrlatch[0]) ? tilehigh : + (decode_tiledata && ~addrlatch[0]) ? tilelow : (decode_bgmap1) ? tileno : 8'bzzzzzzzz) : 8'bzzzzzzzz; always @(posedge clk) begin + rdlatch <= rd; + addrlatch <= addr; if (wr) case (addr) `ADDR_LCDC: rLCDC <= data; diff --git a/Sound1.v b/Sound1.v index 21b1dec..ca97b17 100644 --- a/Sound1.v +++ b/Sound1.v @@ -23,18 +23,23 @@ module Sound1( reg [3:0] delta = 4'b1111; reg toggle = 0; reg [3:0] snd_out = 0; + + reg rdlatch; + reg [15:0] addrlatch; assign snd_data = en ? snd_out : 0; - assign data = rd ? - addr == `ADDR_NR10 ? nr10 : - addr == `ADDR_NR11 ? nr11 : - addr == `ADDR_NR12 ? nr12 : - addr == `ADDR_NR13 ? nr13 : - addr == `ADDR_NR14 ? nr14 : 8'bzzzzzzzz + assign data = rdlatch ? + addrlatch == `ADDR_NR10 ? nr10 : + addrlatch == `ADDR_NR11 ? nr11 : + addrlatch == `ADDR_NR12 ? nr12 : + addrlatch == `ADDR_NR13 ? nr13 : + addrlatch == `ADDR_NR14 ? nr14 : 8'bzzzzzzzz : 8'bzzzzzzzz; always @ (posedge core_clk) begin + rdlatch <= rd; + addrlatch <= addr; if(en && wr) begin case(addr) `ADDR_NR10: nr10 <= data; diff --git a/Sound2.v b/Sound2.v index cf8e83a..ef38263 100644 --- a/Sound2.v +++ b/Sound2.v @@ -24,15 +24,20 @@ module Sound2( reg [3:0] snd_out = 0; assign snd_data = en ? snd_out : 0; + + reg rdlatch; + reg [15:0] addrlatch; - assign data = rd ? - addr == `ADDR_NR21 ? nr21 : - addr == `ADDR_NR22 ? nr22 : - addr == `ADDR_NR23 ? nr23 : - addr == `ADDR_NR24 ? nr24 : 8'bzzzzzzzz + assign data = rdlatch ? + addrlatch == `ADDR_NR21 ? nr21 : + addrlatch == `ADDR_NR22 ? nr22 : + addrlatch == `ADDR_NR23 ? nr23 : + addrlatch == `ADDR_NR24 ? nr24 : 8'bzzzzzzzz : 8'bzzzzzzzz; always @ (posedge core_clk) begin + rdlatch <= rd; + addrlatch <= addr; if(en && wr) begin case(addr) `ADDR_NR21: nr21 <= data; diff --git a/Soundcore.v b/Soundcore.v index 626001d..70c4db1 100644 --- a/Soundcore.v +++ b/Soundcore.v @@ -29,14 +29,19 @@ module Soundcore( (nr51[7] ? sndout4 : 4'b0); assign sndout3 = 0; assign sndout4 = 0; - - assign data = rd ? - addr == `ADDR_NR50 ? nr50 : - addr == `ADDR_NR51 ? nr51 : - addr == `ADDR_NR52 ? nr52 : 8'bzzzzzzzz + + reg rdlatch; + reg [15:0] addrlatch; + + assign data = rdlatch ? + addrlatch == `ADDR_NR50 ? nr50 : + addrlatch == `ADDR_NR51 ? nr51 : + addrlatch == `ADDR_NR52 ? nr52 : 8'bzzzzzzzz : 8'bzzzzzzzz; always @ (posedge core_clk) begin + rdlatch <= rd; + addrlatch <= addr; if(wr) begin case(addr) `ADDR_NR50: nr50 <= data; diff --git a/System.v b/System.v index 4d0ddbb..ebc9be4 100644 --- a/System.v +++ b/System.v @@ -6,6 +6,7 @@ module ROM( input clk, input wr, rd); + reg rdlatch = 0; reg [7:0] odata; // synthesis attribute ram_style of rom is block @@ -13,9 +14,11 @@ module ROM( initial $readmemh("rom.hex", rom); wire decode = address[15:13] == 0; - always @(posedge clk) + always @(posedge clk) begin + rdlatch <= rd && decode; odata <= rom[address[10:0]]; - assign data = (rd && decode) ? odata : 8'bzzzzzzzz; + end + assign data = rdlatch ? odata : 8'bzzzzzzzz; endmodule module BootstrapROM( @@ -24,12 +27,15 @@ module BootstrapROM( input clk, input wr, rd); + reg rdlatch = 0; reg [7:0] brom [255:0]; initial $readmemh("bootstrap.hex", brom); wire decode = address[15:8] == 0; wire [7:0] odata = brom[address[7:0]]; - assign data = (rd && decode) ? odata : 8'bzzzzzzzz; + always @(posedge clk) + rdlatch <= rd && decode; + assign data = rdlatch ? odata : 8'bzzzzzzzz; endmodule module MiniRAM( @@ -41,13 +47,15 @@ module MiniRAM( reg [7:0] ram [127:0]; wire decode = (address >= 16'hFF80) && (address <= 16'hFFFE); + reg rdlatch = 0; reg [7:0] odata; - assign data = (rd && decode) ? odata : 8'bzzzzzzzz; + assign data = rdlatch ? odata : 8'bzzzzzzzz; always @(posedge clk) begin - if (decode) // This has to go this way. The only way XST knows how to do - begin // block ram is chip select, write enable, and always + rdlatch <= rd && decode; + if (decode) // This has to go this way. The only way XST knows how to do + begin // block ram is chip select, write enable, and always if (wr) // reading. "else if rd" does not cut it ... ram[address[6:0]] <= data; odata <= ram[address[6:0]]; @@ -69,6 +77,10 @@ module CellularRAM( parameter ADDR_PROGADDRL = 16'hFF62; parameter ADDR_PROGDATA = 16'hFF63; + reg rdlatch = 0, wrlatch = 0; + reg [15:0] addrlatch = 0; + reg [7:0] datalatch = 0; + reg [7:0] progaddrh, progaddrm, progaddrl; assign cr_nADV = 0; /* Addresses are always valid! :D */ @@ -78,30 +90,35 @@ module CellularRAM( assign cr_CRE = 0; /* Data writes, not config */ assign cr_CLK = 0; /* Clock? I think not! */ - wire decode = (address[15:14] == 2'b00) /* extrom */ || (address[15:13] == 3'b101) /* extram */ || (address == ADDR_PROGDATA); + wire decode = (addrlatch[15:14] == 2'b00) /* extrom */ || (addrlatch[15:13] == 3'b101) /* extram */ || (addrlatch == ADDR_PROGDATA); - assign cr_nOE = decode ? ~rd : 1; - assign cr_nWE = decode ? ~wr : 1; + assign cr_nOE = decode ? ~rdlatch : 1; + assign cr_nWE = decode ? ~wrlatch : 1; - assign cr_DQ = (~cr_nOE) ? 16'bzzzzzzzzzzzzzzzz : {8'b0, data}; - assign cr_A = (address[15:14] == 2'b00) ? /* extrom */ {9'b0,address[13:0]} : - (address[15:13] == 3'b101) ? {1'b1, 9'b0, address[12:0]} : - (address == ADDR_PROGDATA) ? {progaddrh[6:0], progaddrm[7:0], progaddrl[7:0]} : + 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]} : 23'b0; reg [7:0] regbuf; - always @(posedge clk) + always @(posedge clk) begin case (address) ADDR_PROGADDRH: if (wr) progaddrh <= data; ADDR_PROGADDRM: if (wr) progaddrm <= data; ADDR_PROGADDRL: if (wr) progaddrl <= data; endcase + rdlatch <= rd; + wrlatch <= wr; + addrlatch <= address; + datalatch <= data; + end - assign data = (rd && decode) ? - (address == ADDR_PROGADDRH) ? progaddrh : - (address == ADDR_PROGADDRM) ? progaddrm : - (address == ADDR_PROGADDRL) ? progaddrl : + assign data = (rdlatch && decode) ? + (addrlatch == ADDR_PROGADDRH) ? progaddrh : + (addrlatch == ADDR_PROGADDRM) ? progaddrm : + (addrlatch == ADDR_PROGADDRL) ? progaddrl : cr_DQ : 8'bzzzzzzzz; endmodule @@ -117,10 +134,12 @@ module InternalRAM( wire decode = (address >= 16'hC000) && (address <= 16'hFDFF); /* This includes echo RAM. */ reg [7:0] odata; - assign data = (rd && decode) ? odata : 8'bzzzzzzzz; + reg rdlatch = 0; + assign data = rdlatch ? odata : 8'bzzzzzzzz; always @(posedge clk) begin + rdlatch <= rd && decode; if (decode) // This has to go this way. The only way XST knows how to do begin // block ram is chip select, write enable, and always if (wr) // reading. "else if rd" does not cut it ... @@ -140,10 +159,12 @@ module Switches( wire decode = address == 16'hFF51; reg [7:0] odata; - assign data = (rd && decode) ? odata : 8'bzzzzzzzz; + reg rdlatch = 0; + assign data = rdlatch ? odata : 8'bzzzzzzzz; always @(posedge clk) begin + rdlatch <= rd && decode; if (decode && rd) odata <= switches; else if (decode && wr) diff --git a/Timer.v b/Timer.v index e46b38b..facf20f 100644 --- a/Timer.v +++ b/Timer.v @@ -11,15 +11,17 @@ module Timer( inout [7:0] data, output reg irq = 0); + reg rdlatch = 0; + reg [15:0] addrlatch = 0; reg [7:0] tima = 0, tma = 0, tac = 0, div = 0; reg ovf = 0; reg [9:0] clkdv = 0; - wire is_tima = addr == `ADDR_TIMA; - wire is_tma = addr == `ADDR_TMA; - wire is_tac = addr == `ADDR_TAC; + wire is_tima = addrlatch == `ADDR_TIMA; + wire is_tma = addrlatch == `ADDR_TMA; + wire is_tac = addrlatch == `ADDR_TAC; - assign data = rd ? + assign data = rdlatch ? is_tima ? tima : is_tma ? tma : is_tac ? tac : @@ -35,6 +37,9 @@ module Timer( always @ (posedge clk) begin + rdlatch <= rd; + addrlatch <= addr; + if(wr) begin case(addr) `ADDR_DIV: div <= 8'b0; diff --git a/Uart.v b/Uart.v index f9d71f4..07f996a 100644 --- a/Uart.v +++ b/Uart.v @@ -10,11 +10,12 @@ module UART( input [15:0] addr, inout [7:0] data, output reg serial = 1); - + + reg rdlatch = 0; wire decode = (addr == `MMAP_ADDR); wire [7:0] odata; - assign data = (rd && decode) ? odata : 8'bzzzzzzzz; + assign data = rdlatch ? odata : 8'bzzzzzzzz; reg [7:0] data_stor = 0; reg [15:0] clkdiv = 0; @@ -27,6 +28,7 @@ module UART( always @ (posedge clk) begin + rdlatch <= rd && decode; /* deal with diqing */ if(newdata) begin data_stor <= data;