Glue the new SDRAM controller into place

This commit is contained in:
David Hunter
2026-04-12 00:01:52 -07:00
parent 7e1c094099
commit bd2c41a0bd
7 changed files with 310 additions and 201 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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];

View File

@@ -7,7 +7,7 @@ dpram.sv
../pcfx_top.sv
../memif_sdram.sv
../sdram.v
../sdram.sv
../fx_bmp.sv
../mach.sv

View File

@@ -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

View File

@@ -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