diff --git a/rtl/memif_sdram.sv b/rtl/memif_sdram.sv index 55beeac..69c522b 100644 --- a/rtl/memif_sdram.sv +++ b/rtl/memif_sdram.sv @@ -1,6 +1,6 @@ // Use external MiSTer SDRAM as memory backing store // -// Copyright (c) 2025 David Hunter +// Copyright (c) 2025-2026 David Hunter // // This program is GPL licensed. See COPYING for the full license. @@ -38,17 +38,35 @@ module memif_sdram input BMP_WEn, output BMP_READYn, + // ROM / RAM loader/saver interface + input [26:0] LS_ADDR, // byte address + input [31:0] LS_DIN, // data input from loader + input LS_WE_REQ, // loader requests write + output LS_WE_ACK, + output [31:0] LS_DOUT, // data output to saver + input LS_RD_REQ, // saver requests read + output LS_RD_ACK, + input SDRAM_CLK, - output SDRAM_CLKREF, - output [24:0] SDRAM_WADDR, - output [31:0] SDRAM_DIN, - output [3:0] SDRAM_BE, - output SDRAM_WE, - input SDRAM_WE_RDY, - output SDRAM_RD, - input SDRAM_RD_RDY, - output [24:0] SDRAM_RADDR, - input [31:0] SDRAM_DOUT + output [26:0] SDRAM_CH1_ADDR, + input [31:0] SDRAM_CH1_DOUT, + output [31:0] SDRAM_CH1_DIN, + output SDRAM_CH1_REQ, + output SDRAM_CH1_RNW, + output [3:0] SDRAM_CH1_BE, + input SDRAM_CH1_READY, + output [26:0] SDRAM_CH2_ADDR, + input [31:0] SDRAM_CH2_DOUT, + output [31:0] SDRAM_CH2_DIN, + output SDRAM_CH2_REQ, + output SDRAM_CH2_RNW, + input SDRAM_CH2_READY, + output [26:0] SDRAM_CH3_ADDR, + input [31:0] SDRAM_CH3_DOUT, + output [31:0] SDRAM_CH3_DIN, + output SDRAM_CH3_REQ, + output SDRAM_CH3_RNW, + input SDRAM_CH3_READY ); `include "memif_sdram_part.svh" @@ -58,9 +76,10 @@ module memif_sdram // With SDRAM_CLK = 100MHz and CPU_CLK/CE = 25MHz, ROM reads take 4 // CPU cycles or 2 wait states. Coincidentally, that's the correct // timing for PC-FX. +// TODO: Verify this -logic ract = '0; -logic wact = '0; +logic ch1_req, ch1_act; +logic ch1_ready, ch1_ready_d = '1; logic [15:0] rom_do; logic rom_start_req; @@ -80,20 +99,33 @@ logic bmp_readyn = '1; logic mem_start_req; logic mem_pend_req = '0; +logic mem_req; +logic mem_act = '0; logic mem_we; logic mem_rdy; logic mem_readyn; -logic sdram_clkref; -logic [24:0] sdram_waddr; -logic [31:0] sdram_din; -logic [3:0] sdram_be; -logic sdram_we; -logic sdram_rd; -logic [24:0] sdram_raddr; +logic ls_rd_req, ls_we_req, ls_req; +logic ls_rd_ack_d = '0, ls_we_ack_d = '0; +logic ls_act = '0; +logic ls_done; +logic ls_sel; -logic sdram_rd_d = '0; -logic sdram_we_d = '0; +logic [26:0] sdram_ch1_addr; +logic [31:0] sdram_ch1_din; +logic [3:0] sdram_ch1_be; +logic sdram_ch1_we; +logic sdram_ch1_req; + +logic sdram_ch1_req_d = '0; + +assign ls_rd_req = LS_RD_REQ ^ ls_rd_ack_d; +assign ls_we_req = LS_WE_REQ ^ ls_we_ack_d; +assign ls_req = ~mem_act & (ls_rd_req | ls_we_req); +assign ls_done = ls_act & SDRAM_CH1_READY; +assign ls_sel = ls_req | ls_act; +assign LS_RD_ACK = ls_rd_ack_d ^ ((LS_RD_REQ ^ ls_rd_ack_d) & ls_done); +assign LS_WE_ACK = ls_we_ack_d ^ ((LS_WE_REQ ^ ls_we_ack_d) & ls_done); assign rom_start_req = ~CPU_BCYSTn & ~ROM_CEn; assign ram_start_req = ~CPU_BCYSTn & ~RAM_CEn; @@ -101,33 +133,39 @@ assign sram_start_req = ~CPU_BCYSTn & ~SRAM_CEn; assign bmp_start_req = ~CPU_BCYSTn & ~BMP_CEn; assign mem_start_req = rom_start_req | ram_start_req | sram_start_req | bmp_start_req; +assign mem_req = ~ls_act & ~mem_act & (mem_start_req | mem_pend_req) & mem_readyn; assign mem_readyn = rom_readyn & ram_readyn & sram_readyn & bmp_readyn; +assign ch1_req = mem_req | ls_req; +assign ch1_act = mem_act | ls_act; +assign ch1_ready = (ch1_ready_d & ~(~ch1_act & ch1_req)) | SDRAM_CH1_READY; + always @(posedge SDRAM_CLK) begin - mem_pend_req <= (mem_pend_req | mem_start_req) & ~(~CPU_RESn | ract | wact); - sdram_rd_d <= SDRAM_RD; - sdram_we_d <= SDRAM_WE; + mem_pend_req <= (mem_pend_req | mem_start_req) & ~(~CPU_RESn | mem_act); + sdram_ch1_req_d <= SDRAM_CH1_REQ; + ch1_ready_d <= ch1_ready; + + if (ls_done) begin + ls_rd_ack_d <= LS_RD_ACK; + ls_we_ack_d <= LS_WE_ACK; + end end always @(posedge SDRAM_CLK) begin - if (~CPU_RESn) begin - ract <= '0; - wact <= '0; - end - else begin - if (sdram_rd_d & ~SDRAM_RD) - ract <= '1; - else if (ract & SDRAM_RD_RDY & ~mem_readyn) - ract <= '0; + if (~ch1_act & SDRAM_CH1_REQ) begin + if (ls_req) + ls_act <= '1; + else if (mem_req) + mem_act <= '1; + end - if (sdram_we_d & ~SDRAM_WE) - wact <= '1; - else if (wact & SDRAM_WE_RDY & ~mem_readyn) - wact <= '0; - end + if (mem_act & (~CPU_RESn | (ch1_ready & ~mem_readyn))) + mem_act <= '0; + if (ls_act & ls_done) + ls_act <= '0; end -assign mem_rdy = (ract & SDRAM_RD_RDY) | (wact & SDRAM_WE_RDY); +assign mem_rdy = mem_act & ch1_ready; always @(posedge CPU_CLK) if (CPU_CE) begin rom_readyn <= ROM_CEn | ~mem_rdy; @@ -136,15 +174,17 @@ always @(posedge CPU_CLK) if (CPU_CE) begin bmp_readyn <= BMP_CEn | ~mem_rdy; end -// SDRAM_DOUT is in the SDRAM_CLK domain. Latching into the CPU_CLK +// SDRAM_CH1_DOUT is in the SDRAM_CLK domain. Latching into the CPU_CLK // domain helps close timing. always @(posedge CPU_CLK) if (CPU_CE) begin - rom_do <= SDRAM_DOUT[15:0]; - ram_do <= SDRAM_DOUT[31:0]; - sram_do <= SDRAM_DOUT[(8 * SRAM_A[0])+:8]; - bmp_do <= SDRAM_DOUT[(8 * BMP_A[0])+:8]; + rom_do <= SDRAM_CH1_DOUT[15:0]; + ram_do <= SDRAM_CH1_DOUT[31:0]; + sram_do <= SDRAM_CH1_DOUT[(8 * SRAM_A[0])+:8]; + bmp_do <= SDRAM_CH1_DOUT[(8 * BMP_A[0])+:8]; end +assign LS_DOUT = SDRAM_CH1_DOUT; + assign ROM_DO = rom_do; assign ROM_READYn = rom_readyn; @@ -159,43 +199,47 @@ assign BMP_READYn = bmp_readyn; always @* begin mem_we = '0; - sdram_waddr = 'X; - sdram_din = 'X; - sdram_be = 'X; - sdram_raddr = 'X; - if (~ROM_CEn) begin - sdram_raddr = ROM_BASE_A + 25'(ROM_A); - sdram_be = '1; + sdram_ch1_addr = 'X; + sdram_ch1_din = 'X; + sdram_ch1_be = 'X; + if (ls_sel) begin + mem_we = ls_we_req; + sdram_ch1_din = LS_DIN; + sdram_ch1_be = '1; + sdram_ch1_addr = LS_ADDR; + end + else if (~ROM_CEn) begin + sdram_ch1_addr = ROM_BASE_A + 27'(ROM_A); + sdram_ch1_be = '1; end else if (~RAM_CEn) begin mem_we = ~RAM_WEn; - sdram_din = RAM_DI; - sdram_be = ~RAM_BEn; - sdram_raddr = RAM_BASE_A + 25'(RAM_A); - sdram_waddr = sdram_raddr; + sdram_ch1_din = RAM_DI; + sdram_ch1_be = ~RAM_BEn; + sdram_ch1_addr = RAM_BASE_A + 27'(RAM_A); end else if (~SRAM_CEn) begin mem_we = ~SRAM_WEn; - sdram_din = {4{SRAM_DI}}; - sdram_be = {2'b00, SRAM_A[0], ~SRAM_A[0]}; - sdram_raddr = SRAM_BASE_A + 25'(SRAM_A); - sdram_waddr = sdram_raddr; + sdram_ch1_din = {4{SRAM_DI}}; + sdram_ch1_be = {2'b00, SRAM_A[0], ~SRAM_A[0]}; + sdram_ch1_addr = SRAM_BASE_A + 27'(SRAM_A); end else if (~BMP_CEn) begin mem_we = ~BMP_WEn; - sdram_din = {4{BMP_DI}}; - sdram_be = {2'b00, BMP_A[0], ~BMP_A[0]}; - sdram_raddr = BMP_BASE_A + 25'(BMP_A); - sdram_waddr = sdram_raddr; + sdram_ch1_din = {4{BMP_DI}}; + sdram_ch1_be = {2'b00, BMP_A[0], ~BMP_A[0]}; + sdram_ch1_addr = BMP_BASE_A + 27'(BMP_A); end end -assign SDRAM_CLKREF = 0;//mem_start_req; -assign SDRAM_WADDR = sdram_waddr; -assign SDRAM_DIN = sdram_din; -assign SDRAM_BE = sdram_be; -assign SDRAM_WE = ~wact & SDRAM_WE_RDY & (mem_start_req | mem_pend_req) & mem_we; -assign SDRAM_RD = ~ract & SDRAM_RD_RDY & (mem_start_req | mem_pend_req) & ~mem_we; -assign SDRAM_RADDR = sdram_raddr; +assign SDRAM_CH1_ADDR = sdram_ch1_addr; +assign SDRAM_CH1_DIN = sdram_ch1_din; +assign SDRAM_CH1_BE = sdram_ch1_be; +assign SDRAM_CH1_RNW = ~mem_we; +assign SDRAM_CH1_REQ = ch1_ready_d & ch1_req; + +// TODO +assign SDRAM_CH2_REQ = '0; +assign SDRAM_CH3_REQ = '0; endmodule diff --git a/rtl/memif_sdram_part.svh b/rtl/memif_sdram_part.svh index d9defeb..8a5d994 100644 --- a/rtl/memif_sdram_part.svh +++ b/rtl/memif_sdram_part.svh @@ -4,7 +4,18 @@ // // This program is GPL licensed. See COPYING for the full license. -localparam [24:0] ROM_BASE_A = 25'h000_0000; // ..00F_FFFF -localparam [24:0] RAM_BASE_A = 25'h010_0000; // ..02F_FFFF -localparam [24:0] SRAM_BASE_A = 25'h080_0000; // ..080_7FFF -localparam [24:0] BMP_BASE_A = 25'h100_0000; // ..17F_FFFF +// The PC-FX has several discrete DRAM memories and controllers. Each +// memory is allocated to a different SDRAM bank to take advantage of +// interleaved access, allowing us to access them near-simultaneously. + +// Bank 0: Memory directly addressable by the CPU +localparam [26:0] ROM_BASE_A = 27'h000_0000; // ..00F_FFFF +localparam [26:0] RAM_BASE_A = 27'h010_0000; // ..02F_FFFF +localparam [26:0] SRAM_BASE_A = 27'h040_0000; // ..040_7FFF +localparam [26:0] BMP_BASE_A = 27'h080_0000; // ..0FF_FFFF + +// Bank 1: KING RAM A +localparam [26:0] KRAMA_BASE_A = 27'h100_0000; // ..107_FFFF + +// Bank 2: KING RAM A +localparam [26:0] KRAMB_BASE_A = 27'h200_0000; // ..207_FFFF diff --git a/rtl/pcfx_top.sv b/rtl/pcfx_top.sv index 1002d27..8a08471 100644 --- a/rtl/pcfx_top.sv +++ b/rtl/pcfx_top.sv @@ -69,11 +69,11 @@ module pcfx_top output [7:0] B ); -reg [24:0] romwr_a; +reg [26:0] romwr_a; reg [31:0] romwr_d; reg romwr_req = 0; wire romwr_ack; -logic [24:0] bk_sdrd_a; +logic [26:0] bk_sdrd_a; logic [31:0] bk_sdrd_din, bk_sdrd_dout; logic bk_sdrd_we_req = 0, bk_sdrd_rd_req = 0; logic bk_sdrd_we_ack, bk_sdrd_rd_ack; @@ -83,53 +83,45 @@ logic [1:0] bk_mounted; ////////////////////////////////////////////////////////////////////// // SDRAM controller -wire sdram_clkref; -wire [24:0] sdram_raddr, sdram_waddr, sdram_ls_addr; -wire [31:0] sdram_din, sdram_dout, sdram_ls_din, sdram_ls_dout; -wire sdram_rd, sdram_rd_rdy; -wire [3:0] sdram_be; -wire sdram_we; -wire sdram_we_rdy; -wire sdram_ls_we_req, sdram_ls_we_ack; -wire sdram_ls_rd_req, sdram_ls_rd_ack; +wire [26:0] sdram_ch1_addr; +wire [31:0] sdram_ch1_din, sdram_ch1_dout; +wire [3:0] sdram_ch1_be; +wire sdram_ch1_rnw, sdram_ch1_req, sdram_ch1_ready; +wire [26:0] sdram_ch2_addr; +wire [31:0] sdram_ch2_din, sdram_ch2_dout; +wire sdram_ch2_rnw, sdram_ch2_req, sdram_ch2_ready; +wire [26:0] sdram_ch3_addr; +wire [31:0] sdram_ch3_din, sdram_ch3_dout; +wire sdram_ch3_rnw, sdram_ch3_req, sdram_ch3_ready; sdram sdram ( - .*, + .*, - .init(~pll_locked), - .clk(clk_ram), - .clkref(sdram_clkref), + .init(~pll_locked), + .clk(clk_ram), - .waddr(sdram_waddr), - .din(sdram_din), - .be(sdram_be), - .we(sdram_we), - .we_rdy(sdram_we_rdy), - - .raddr(sdram_raddr), - .rd(sdram_rd), - .rd_rdy(sdram_rd_rdy), - .dout(sdram_dout), - - .ls_addr(sdram_ls_addr), - .ls_din(sdram_ls_din), - .ls_we_req(sdram_ls_we_req), - .ls_we_ack(sdram_ls_we_ack), - .ls_dout(sdram_ls_dout), - .ls_rd_req(sdram_ls_rd_req), - .ls_rd_ack(sdram_ls_rd_ack) + .ch1_addr(sdram_ch1_addr), + .ch1_dout(sdram_ch1_dout), + .ch1_din(sdram_ch1_din), + .ch1_req(sdram_ch1_req), + .ch1_rnw(sdram_ch1_rnw), + .ch1_be(sdram_ch1_be), + .ch1_ready(sdram_ch1_ready), + .ch2_addr(sdram_ch2_addr), + .ch2_dout(sdram_ch2_dout), + .ch2_din(sdram_ch2_din), + .ch2_req(sdram_ch2_req), + .ch2_rnw(sdram_ch2_rnw), + .ch2_ready(sdram_ch2_ready), + .ch3_addr(sdram_ch3_addr), + .ch3_dout(sdram_ch3_dout), + .ch3_din(sdram_ch3_din), + .ch3_req(sdram_ch3_req), + .ch3_rnw(sdram_ch3_rnw), + .ch3_ready(sdram_ch3_ready) ); -assign sdram_ls_addr = ioctl_download ? romwr_a : bk_sdrd_a; -assign sdram_ls_din = ioctl_download ? romwr_d : bk_sdrd_dout; -assign sdram_ls_we_req = romwr_req ^ bk_sdrd_we_req; -assign bk_sdrd_din = sdram_ls_dout; -assign sdram_ls_rd_req = bk_sdrd_rd_req; -assign romwr_ack = sdram_ls_we_ack ^ bk_sdrd_we_req; -assign bk_sdrd_we_ack = sdram_ls_we_ack ^ romwr_req; -assign bk_sdrd_rd_ack = sdram_ls_rd_ack; - ////////////////////////////////////////////////////////////////////// // Computer assembly @@ -180,10 +172,17 @@ wire bmp_cen; wire bmp_wen; wire bmp_readyn; +wire [26:0] ls_addr; +wire [31:0] ls_din, ls_dout; +wire ls_we_req, ls_we_ack; +wire ls_rd_req, ls_rd_ack; + wire clk_cpu = clk_sys; wire reset_int = reset | ioctl_download; initial cpu_ce = 0; +initial reset_cpu = 1; +initial cpu_resn = 0; always @(posedge clk_cpu) begin cpu_ce <= ~cpu_ce; @@ -279,17 +278,34 @@ memif_sdram memif_sdram .BMP_WEn(bmp_wen), .BMP_READYn(bmp_readyn), + .LS_ADDR(ls_addr), + .LS_DIN(ls_din), + .LS_WE_REQ(ls_we_req), + .LS_WE_ACK(ls_we_ack), + .LS_DOUT(ls_dout), + .LS_RD_REQ(ls_rd_req), + .LS_RD_ACK(ls_rd_ack), + .SDRAM_CLK(clk_ram), - .SDRAM_CLKREF(sdram_clkref), - .SDRAM_WADDR(sdram_waddr), - .SDRAM_DIN(sdram_din), - .SDRAM_BE(sdram_be), - .SDRAM_WE(sdram_we), - .SDRAM_WE_RDY(sdram_we_rdy), - .SDRAM_RADDR(sdram_raddr), - .SDRAM_RD(sdram_rd), - .SDRAM_RD_RDY(sdram_rd_rdy), - .SDRAM_DOUT(sdram_dout) + .SDRAM_CH1_ADDR(sdram_ch1_addr), + .SDRAM_CH1_DOUT(sdram_ch1_dout), + .SDRAM_CH1_DIN(sdram_ch1_din), + .SDRAM_CH1_REQ(sdram_ch1_req), + .SDRAM_CH1_RNW(sdram_ch1_rnw), + .SDRAM_CH1_BE(sdram_ch1_be), + .SDRAM_CH1_READY(sdram_ch1_ready), + .SDRAM_CH2_ADDR(sdram_ch2_addr), + .SDRAM_CH2_DOUT(sdram_ch2_dout), + .SDRAM_CH2_DIN(sdram_ch2_din), + .SDRAM_CH2_REQ(sdram_ch2_req), + .SDRAM_CH2_RNW(sdram_ch2_rnw), + .SDRAM_CH2_READY(sdram_ch2_ready), + .SDRAM_CH3_ADDR(sdram_ch3_addr), + .SDRAM_CH3_DOUT(sdram_ch3_dout), + .SDRAM_CH3_DIN(sdram_ch3_din), + .SDRAM_CH3_REQ(sdram_ch3_req), + .SDRAM_CH3_RNW(sdram_ch3_rnw), + .SDRAM_CH3_READY(sdram_ch3_ready) ); fx_bmp bmp @@ -313,6 +329,15 @@ fx_bmp bmp .RAM_READYn(bmp_readyn) ); +assign ls_addr = ioctl_download ? romwr_a : bk_sdrd_a; +assign ls_din = ioctl_download ? romwr_d : bk_sdrd_dout; +assign ls_we_req = romwr_req ^ bk_sdrd_we_req; +assign ls_rd_req = bk_sdrd_rd_req; +assign bk_sdrd_din = ls_dout; +assign romwr_ack = ls_we_ack ^ bk_sdrd_we_req; +assign bk_sdrd_we_ack = ls_we_ack ^ romwr_req; +assign bk_sdrd_rd_ack = ls_rd_ack; + ////////////////////////////////////////////////////////////////////// // ROM loader @@ -349,7 +374,7 @@ always @(posedge clk_sys) begin romwr_a1 <= ~romwr_a1; end else if(ioctl_wait && (romwr_req == romwr_ack)) begin ioctl_wait <= 0; - romwr_a <= romwr_a + 25'd4; + romwr_a <= romwr_a + 27'd4; end end end @@ -520,7 +545,7 @@ end // SD card transfer buffer logic bk_sdrd_copying = 0; -logic [24:0] bk_sdrd_base_a; +logic [26:0] bk_sdrd_base_a; logic [7:0] sdbuf_a; logic sdbuf_a0, sdbuf_a0_d; @@ -533,7 +558,7 @@ assign bk_sdrd_base_a = sd_vd ? BMP_BASE_A : SRAM_BASE_A; always @(posedge clk_sys) begin if (~bk_sdrd_copying & (bk_sdrd_copy_req != bk_sdrd_copy_ack)) begin bk_sdrd_copying <= 1; - bk_sdrd_a <= bk_sdrd_base_a + 25'({sd_lba, 9'b0}); + bk_sdrd_a <= bk_sdrd_base_a + 27'({sd_lba, 9'b0}); sdbuf_a0 <= '0; if (bk_loading) sdbuf_rden <= 1; @@ -566,7 +591,7 @@ always @(posedge clk_sys) begin else bk_sdrd_rd_req <= ~bk_sdrd_rd_req; end - bk_sdrd_a <= bk_sdrd_a + 25'd4; + bk_sdrd_a <= bk_sdrd_a + 27'd4; end sdbuf_a0 <= ~sdbuf_a0; end diff --git a/rtl/sdram.sv b/rtl/sdram.sv index 26f628f..3df6407 100644 --- a/rtl/sdram.sv +++ b/rtl/sdram.sv @@ -89,9 +89,9 @@ localparam sdram_startup_cycles= 14'd12100;// 100us, plus a little more, @ 100MH localparam cycles_per_refresh = 14'd300; // (64000*64)/8192-1 Calc'd as (64ms @ 64MHz)/8192 rose localparam startup_refresh_max = 14'b11111111111111; localparam startup_mode_cnt = startup_refresh_max - 7; -localparam startup_ref2_cnt = startup_mode_cnt - TRC_MIN; -localparam startup_ref1_cnt = startup_ref2_cnt - TRC_MIN; -localparam startup_pchg_cnt = startup_ref1_cnt - TRP_MIN; +localparam startup_ref2_cnt = 14'(startup_mode_cnt - TRC_MIN); +localparam startup_ref1_cnt = 14'(startup_ref2_cnt - TRC_MIN); +localparam startup_pchg_cnt = 14'(startup_ref1_cnt - TRP_MIN); // SDRAM commands wire [2:0] CMD_NOP = 3'b111; @@ -106,6 +106,7 @@ reg [13:0] refresh_count = startup_refresh_max - sdram_startup_cycles; reg [3:0] refresh_wait; reg [2:0] command; reg [15:0] dqout; +reg dqoe = 0; // BAnk STate localparam BAST_IDLE = 0; @@ -121,7 +122,7 @@ localparam BAST_PRE = 9; reg [3:0] barq, barq_d; // access request reg [3:0] barnw; // read / not write -reg [11:0] barow [4]; // row address +reg [12:0] barow [4]; // row address reg [9:0] bacol [4]; // column address reg [31:0] badin [4]; // data to write reg [3:0] babe [4]; // byte enables @@ -158,7 +159,7 @@ reg [1:0] bbsba_d; // last bank reg [3:0] bbscact; // cmd bus cycle activity bitmap reg [3:0] bbsdact; // data bus cycle activity bitmap reg bbsschn; // bank was newly scheduled -reg [3:0] bbsschban; // the newly scheduled bank +reg [1:0] bbsschban; // the newly scheduled bank reg [3:0] bbsschv; // schedule filled reg [1:0] bbsschba [4]; // bank schedule @@ -244,16 +245,16 @@ always @(posedge clk) begin bawait[b] <= bawait[b] - 1'd1; case (bast[b]) - BAST_IDLE: if (bbsba == b) begin + BAST_IDLE: if (bbsba == b[1:0]) begin if (~bapause && barq[b]) begin bast[b] <= BAST_ACT; end end BAST_ACT: begin bast[b] <= BAST_ACT_WAIT; - bawait[b] <= TRCD_MIN - 2; + bawait[b] <= 4'(TRCD_MIN - 2); end - BAST_ACT_WAIT: if (bbsba == b) begin + BAST_ACT_WAIT: if (bbsba == b[1:0]) begin if (bawait[b] == 0) begin bast[b] <= barnw[b] ? BAST_R_CMD : BAST_W_CMD; end @@ -268,19 +269,19 @@ always @(posedge clk) begin BAST_R: if (bawait[b] == 0) begin bast[b] <= BAST_PRE; - bawait[b] <= (TRP_MIN-(BURST_LENGTH-1)) - 2; + bawait[b] <= 4'(TRP_MIN-(BURST_LENGTH-1)) - 2; end BAST_W_CMD: begin bast[b] <= BAST_W_CMD_2; end BAST_W_CMD_2: begin bast[b] <= BAST_W_REC; - bawait[b] <= TWR_MIN - 1; + bawait[b] <= 4'(TWR_MIN - 1); end BAST_W_REC: if (bawait[b] == 0) begin bast[b] <= BAST_PRE; - bawait[b] <= TRP_MIN - 2; + bawait[b] <= 4'(TRP_MIN - 2); end BAST_PRE: if (bawait[b] == 0) begin @@ -290,6 +291,11 @@ always @(posedge clk) begin end end +initial begin + for (int i = 0; i < 4; i++) + bast[i] = BAST_IDLE; +end + // Bus bank scheduler always @* begin bbsba = bbsba_d; @@ -304,9 +310,9 @@ always @* begin // Nothing scheduled yet. Any volunteers? for (int b = 3; b >= 0; b--) begin if (bbsschn == 0) begin - bbsschban = b; + bbsschban = b[1:0]; - if ((bacreq[b] | badreq[b]) & + if (|(bacreq[b] | badreq[b]) & ~|(bacreq[b] & bbscact) & ~|(badreq[b] & bbsdact)) bbsschn = 1; end @@ -347,6 +353,12 @@ always @(posedge clk) begin bbsdact <= {1'b0, bbsdact[$left(bbsdact):1]} | badreq[bbsba]; end +initial begin + ch1_ready = 0; + ch2_ready = 0; + ch3_ready = 0; +end + always @(posedge clk) begin reg [CAS_LATENCY+BURST_LENGTH:0] data_ready_delay1, data_ready_delay2, data_ready_delay3; @@ -372,7 +384,7 @@ always @(posedge clk) begin if(data_ready_delay3[0]) ch3_dout[31:16] <= SDRAM_DQ; if(data_ready_delay3[0]) ch3_ready <= 1; - dqout <= 16'bZ; + dqoe <= 0; command <= CMD_NOP; SDRAM_A[12:11] <= 2'b11; // DQM @@ -401,7 +413,7 @@ always @(posedge clk) begin SDRAM_A <= MODE; end - if (!refresh_count) begin + if (refresh_count == 0) begin state <= STATE_ACTIVE; refresh_count <= 0; end @@ -409,7 +421,7 @@ always @(posedge clk) begin STATE_REFRESH: begin // mask possible refresh to reduce colliding. - if (refresh_wait == TRC_MIN) begin + if (refresh_wait == 4'(TRC_MIN)) begin // Start the refresh cycle. command <= CMD_AUTO_REFRESH; refresh_count <= refresh_count - cycles_per_refresh + 1'd1; @@ -428,7 +440,7 @@ always @(posedge clk) begin if (baidle && refresh_count > cycles_per_refresh) begin // Priority is to issue a refresh if one is outstanding state <= STATE_REFRESH; - refresh_wait <= TRC_MIN; + refresh_wait <= 4'(TRC_MIN); end BAST_ACT: begin SDRAM_BA <= bbsba; @@ -455,6 +467,7 @@ always @(posedge clk) begin SDRAM_A[9:0] <= bacol[bbsba]; command <= CMD_WRITE; dqout <= badin[bbsba][15:0]; + dqoe <= 1; end BAST_W_CMD_2: begin SDRAM_A[12:11] <= ~babe[bbsba][3:2]; // DQM for 2nd beat @@ -462,6 +475,7 @@ always @(posedge clk) begin SDRAM_A[0] <= 1; command <= CMD_WRITE; dqout <= badin[bbsba][31:16]; + dqoe <= 1; if(bbsba == 0) ch1_ready <= 1; else if(bbsba == 1) ch2_ready <= 1; else ch3_ready <= 1; @@ -479,7 +493,7 @@ always @(posedge clk) begin end end -assign SDRAM_DQ = dqout; +assign SDRAM_DQ = dqoe ? dqout : 'Z; assign SDRAM_nCS = 0; assign SDRAM_nRAS = command[2]; assign SDRAM_nCAS = command[1]; diff --git a/rtl/tb/pcfx_top.files b/rtl/tb/pcfx_top.files index 43a9975..a4e42b6 100644 --- a/rtl/tb/pcfx_top.files +++ b/rtl/tb/pcfx_top.files @@ -7,7 +7,7 @@ dpram.sv ../pcfx_top.sv ../memif_sdram.sv -../sdram.v +../sdram.sv ../fx_bmp.sv ../mach.sv diff --git a/rtl/tb/pcfx_top_tb.gtkw b/rtl/tb/pcfx_top_tb.gtkw index 8b95bbd..7295c9c 100644 --- a/rtl/tb/pcfx_top_tb.gtkw +++ b/rtl/tb/pcfx_top_tb.gtkw @@ -1,15 +1,15 @@ [*] [*] GTKWave Analyzer v3.4.0 (w)1999-2022 BSI -[*] Fri Nov 28 04:55:18 2025 +[*] Sun Apr 12 06:31:32 2026 [*] [dumpfile] "/Users/dhunter/src/mister/PCFX_MiSTer/rtl/tb/pcfx_top_tb.vcd" -[dumpfile_mtime] "Fri Nov 28 04:50:14 2025" -[dumpfile_size] 2031594993 +[dumpfile_mtime] "Sun Apr 12 06:28:28 2026" +[dumpfile_size] 929360634 [savefile] "/Users/dhunter/src/mister/PCFX_MiSTer/rtl/tb/pcfx_top_tb.gtkw" [timestart] 0 [size] 1333 600 [pos] -1 -1 -*-24.157753 66150120 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +*-21.385801 163720 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [markername] AA [markername] BB [markername] CC @@ -39,47 +39,66 @@ [treeopen] pcfx_top_tb. [treeopen] pcfx_top_tb.pcfx_top. [treeopen] pcfx_top_tb.pcfx_top.memif_sdram. -[treeopen] pcfx_top_tb.sdram_mem. +[treeopen] pcfx_top_tb.pcfx_top.sdram. +[treeopen] pcfx_top_tb.sdrb. +[treeopen] pcfx_top_tb.sdrb.u1a. [sst_width] 255 -[signals_width] 203 +[signals_width] 252 [sst_expanded] 1 [sst_vpaned_height] 159 -@22 -pcfx_top_tb.sdrb.u1a.col[9:0] -pcfx_top_tb.sdrb.u1a.din[15:0] @28 -pcfx_top_tb.sdrb.u1a.wr_dqm[1:0] -pcfx_top_tb.sdrb.u1a.DQMH -pcfx_top_tb.sdrb.u1a.DQML -@22 -pcfx_top_tb.sdrb.u1a.DQ[15:0] -pcfx_top_tb.sdrb.u1a.A[12:0] -@28 -pcfx_top_tb.pcfx_top.sdram.we -pcfx_top_tb.pcfx_top.sdram.we_rdy -@420 -pcfx_top_tb.sdrb.u1a.wr_cnt -@22 -pcfx_top_tb.sdrb.u1a.wr_din[15:0] -@28 -pcfx_top_tb.pcfx_top.sdram.rd -pcfx_top_tb.pcfx_top.sdram.rd_rdy -@200 -- +pcfx_top_tb.pcfx_top.mach.cpu.RESn @22 pcfx_top_tb.pcfx_top.mach.A[31:0] pcfx_top_tb.pcfx_top.mach.cpu.D_I[31:0] pcfx_top_tb.pcfx_top.mach.cpu.D_O[31:0] @28 pcfx_top_tb.pcfx_top.mach.cpu.BCYSTn +pcfx_top_tb.pcfx_top.mach.cpu.READYn +@200 +- +@28 pcfx_top_tb.pcfx_top.memif_sdram.RAM_CEn -pcfx_top_tb.pcfx_top.memif_sdram.SDRAM_WE_RDY +pcfx_top_tb.pcfx_top.memif_sdram.SDRAM_CH1_REQ +pcfx_top_tb.pcfx_top.memif_sdram.SDRAM_CH1_READY +pcfx_top_tb.pcfx_top.memif_sdram.SDRAM_CH1_RNW +@22 +pcfx_top_tb.pcfx_top.memif_sdram.SDRAM_CH1_DOUT[31:0] +@28 +pcfx_top_tb.pcfx_top.memif_sdram.ch1_req +pcfx_top_tb.pcfx_top.memif_sdram.ch1_ready +pcfx_top_tb.pcfx_top.memif_sdram.ch1_ready_d pcfx_top_tb.pcfx_top.memif_sdram.ram_start_req pcfx_top_tb.pcfx_top.memif_sdram.ram_readyn -pcfx_top_tb.pcfx_top.memif_sdram.ract -@29 -pcfx_top_tb.pcfx_top.memif_sdram.wact +@22 +pcfx_top_tb.pcfx_top.memif_sdram.ROM_DO[15:0] @28 +pcfx_top_tb.pcfx_top.memif_sdram.mem_start_req +pcfx_top_tb.pcfx_top.memif_sdram.mem_pend_req +@29 +pcfx_top_tb.pcfx_top.memif_sdram.mem_req +@28 +pcfx_top_tb.pcfx_top.memif_sdram.mem_act pcfx_top_tb.pcfx_top.memif_sdram.mem_readyn +pcfx_top_tb.pcfx_top.memif_sdram.LS_RD_REQ +pcfx_top_tb.pcfx_top.memif_sdram.LS_RD_ACK +pcfx_top_tb.pcfx_top.memif_sdram.LS_WE_REQ +pcfx_top_tb.pcfx_top.memif_sdram.LS_WE_ACK +pcfx_top_tb.pcfx_top.memif_sdram.ls_req +pcfx_top_tb.pcfx_top.memif_sdram.ls_act +pcfx_top_tb.pcfx_top.memif_sdram.ls_sel +pcfx_top_tb.pcfx_top.memif_sdram.ls_rd_ack_d +pcfx_top_tb.pcfx_top.memif_sdram.ls_we_ack_d +pcfx_top_tb.pcfx_top.memif_sdram.ls_done +@200 +- +@24 +pcfx_top_tb.pcfx_top.sdram.state[3:0] +@28 +pcfx_top_tb.pcfx_top.sdram.ch1_req +pcfx_top_tb.pcfx_top.sdram.ch1_rnw +@22 +pcfx_top_tb.pcfx_top.sdram.ch1_addr[26:0] +pcfx_top_tb.pcfx_top.sdram.ch1_dout[31:0] [pattern_trace] 1 [pattern_trace] 0 diff --git a/rtl/tb/pcfx_top_tb.sv b/rtl/tb/pcfx_top_tb.sv index 45731a8..8e805ce 100644 --- a/rtl/tb/pcfx_top_tb.sv +++ b/rtl/tb/pcfx_top_tb.sv @@ -17,8 +17,9 @@ import core_pkg::hmi_t; module pcfx_top_tb; -logic reset; -logic clk_sys, clk_ram; +logic reset = 1; +logic clk_sys = 1; +logic clk_ram = 1; initial begin $timeformat(-6, 0, " us", 1); @@ -46,6 +47,8 @@ wire SDRAM_nCAS; wire SDRAM_nRAS; wire SDRAM_nWE; +assign SDRAM_CLK = clk_ram; + sdram_xsds sdrb (.*); ////////////////////////////////////////////////////////////////////// @@ -76,7 +79,7 @@ logic bk_load = 0; logic bk_save = 0; logic bmp_eject_rom = 0; -hmi_t hmi; +hmi_t hmi = '0; wire pce; wire hbl, vbl; @@ -147,14 +150,6 @@ pcfx_top pcfx_top .B(b) ); -initial begin - reset = 1; - clk_sys = 1; - clk_ram = 1; - - hmi = '0; -end - initial forever begin :clkgen_sys #0.01 clk_sys = ~clk_sys; // 50 MHz end @@ -163,19 +158,20 @@ initial forever begin :clkgen_ram #0.005 clk_ram = ~clk_ram; // 100 MHz end +initial reset_sys = 1; always @(posedge clk_sys) reset_sys <= reset; ////////////////////////////////////////////////////////////////////// -task sdram_read(input [24:0] addr, output [15:0] d); +task sdram_read(input [26:0] addr, output [15:0] d); sdrb.u1a.read(pcfx_top.sdram.addr_to_bank(addr), pcfx_top.sdram.addr_to_row(addr), pcfx_top.sdram.addr_to_col(addr), d); endtask -task sdram_write(input [24:0] addr, input [15:0] d); +task sdram_write(input [26:0] addr, input [15:0] d); sdrb.u1a.write(pcfx_top.sdram.addr_to_bank(addr), pcfx_top.sdram.addr_to_row(addr), pcfx_top.sdram.addr_to_col(addr), @@ -249,11 +245,11 @@ endtask ////////////////////////////////////////////////////////////////////// -task load_file(input [24:0] base, input string fn); +task load_file(input [26:0] base, input string fn); integer fin; integer code; logic [15:0] data; -logic [24:0] addr; +logic [26:0] addr; begin fin = $fopen(fn, "rb"); assert(fin != 0) else $error("Unable to open file %s", fn); @@ -412,7 +408,7 @@ endtask task verify_bk_load(int vd); bit [15:0] dfile, dram; -bit [24:0] base, addr; +bit [26:0] base, addr; integer code; if (sd_size[vd] == 0) return; @@ -425,7 +421,7 @@ integer code; dfile = {dfile[7:0], dfile[15:8]}; // $fread is big-endian sdram_read(base + addr, dram); assert(dfile == dram) else $error("Wanted %x, got %x @ addr. %x", dfile, dram, addr); - addr += 25'd2; + addr += 27'd2; end endtask @@ -489,7 +485,7 @@ end event running; initial #0 begin - #10 ; // wait for sdram init. + #150 ; // wait for sdram init. load_rombios(); `ifdef LOAD_BMP_ROM @@ -516,8 +512,8 @@ end initial begin @(running) ; - repeat (4) #(1000e3) ; - //#(500e3) ; + //repeat (4) #(1000e3) ; + #(500e3) ; `ifdef SAVE_SRAMS if (bk_ena) begin