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;
end
else
ihold <= ihold | iflag;
+ rdlatch <= rd;
+ addrlatch <= addr;
end
endmodule
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;
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;
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;
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;
(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;
input clk,
input wr, rd);
+ reg rdlatch = 0;
reg [7:0] odata;
// synthesis attribute ram_style of rom is block
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(
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(
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]];
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 */
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
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 ...
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)
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 :
always @ (posedge clk)
begin
+ rdlatch <= rd;
+ addrlatch <= addr;
+
if(wr) begin
case(addr)
`ADDR_DIV: div <= 8'b0;
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;
always @ (posedge clk)
begin
+ rdlatch <= rd && decode;
/* deal with diqing */
if(newdata) begin
data_stor <= data;