RIDE/rtl/top.v
2024-12-31 14:41:07 +13:00

230 lines
5.5 KiB
Verilog

`timescale 1ns / 1ps
/*
* Copyright (C) 2023 Matthew Harlum <matt@harlum.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
module RIDE(
inout [15:12] DBUS,
input [23:1] ADDR,
input BERR_n,
input UDS_n,
input LDS_n,
input RW,
input AS_n,
input RESET_n,
input ECLK,
input CFGIN_n,
output DTACK_n,
inout OVR_n,
output CFGOUT_n,
// IDE stuff
input IDE_ENABLE,
output IOR_n,
output IOW_n,
output IDECS1_n,
output IDECS2_n,
output IDEBUF_OE,
output IDE_ROMEN,
output [1:0] ROM_BANK,
// SDRAM Stuff
input [1:0] RAM_SIZE,
input MEMCLK,
output MEMW_n,
output RAS_n,
output CAS_n,
output CKE,
output DQML,
output DQMH,
output RAMCS_n,
output [11:0] MA,
output [1:0] BA,
output RAMOE_n
);
`include "globalparams.vh"
wire autoconfig_cycle;
wire [3:0] autoconfig_dout;
wire ram_dtack;
wire autoconf_dtack;
wire idereg_dtack;
reg ovr_detect;
wire ram_access;
wire ide_access;
wire idereg_access;
wire otherram_en;
wire [3:0] ideregister_dout;
wire ide_enabled;
wire ovl;
wire enable_maprom;
wire ram_ready;
wire bonus_en;
reg [1:0] uds_n_sync;
reg [1:0] lds_n_sync;
reg [2:0] as_n_sync;
reg [1:0] rw_sync;
// Detect if OVR has been connected
// A weak pull-down resistor will pull this signal low if disconnected.
//
// IDE & 8M Fast RAM can operate without OVR
// But A0 & C0 RAM can't
always @(posedge RESET_n) begin
ovr_detect <= OVR_n;
end
always @(posedge MEMCLK or negedge RESET_n) begin
if (!RESET_n) begin
uds_n_sync <= 2'b11;
lds_n_sync <= 2'b11;
as_n_sync <= 3'b111;
rw_sync <= 2'b11;
end else begin
uds_n_sync[1:0] <= {uds_n_sync[0],UDS_n};
lds_n_sync[1:0] <= {lds_n_sync[0],LDS_n};
as_n_sync[2:0] <= {as_n_sync[1:0],AS_n};
rw_sync <= {rw_sync[0],RW};
end
end
reg [1:0] z2_state;
always @(posedge MEMCLK or negedge RESET_n) begin
if (!RESET_n) begin
z2_state <= Z2_IDLE;
end else begin
case (z2_state)
Z2_IDLE:
begin
if (~as_n_sync[1] && (ram_access || autoconfig_cycle || idereg_access)) begin
z2_state <= Z2_START;
end
end
Z2_START:
begin
if (!uds_n_sync[1] || !lds_n_sync[1]) begin
z2_state <= Z2_DATA;
end
end
Z2_DATA:
begin
if (ram_dtack || autoconf_dtack || idereg_dtack) begin
z2_state <= Z2_END;
end
end
Z2_END:
if (as_n_sync[1]) begin
z2_state <= Z2_IDLE;
end
endcase
end
end
Autoconfig AUTOCONFIG (
.addr (ADDR),
.as_n (as_n_sync[1]),
.rw (rw_sync[1]),
.clk (MEMCLK),
.din (DBUS[15:12]),
.reset_n (RESET_n),
.ram_access (ram_access),
.ram_size (RAM_SIZE),
.ovr_detect (ovr_detect),
.bonus_en (bonus_en),
.ide_enabled (IDE_ENABLE),
.autoconfig_cycle (autoconfig_cycle),
.dout (autoconfig_dout),
.z2_state (z2_state),
.dtack (autoconf_dtack),
.ide_access (ide_access),
.enable_maprom (enable_maprom),
.cfgin_n (CFGIN_n),
.cfgout_n (CFGOUT_n),
.ovl (ovl)
);
// Force address to F8xxxx if ovl active for early boot overlay
wire [4:0] ram_addr_hi = (ovl) ? {4'b1111, (ADDR[19] | !ADDR[23])} : ADDR[23:19];
SDRAM SDRAM (
.addr ({ram_addr_hi, ADDR[18:1]}),
.z2_state (z2_state),
.uds_n (uds_n_sync[1]),
.lds_n (lds_n_sync[1]),
.ram_cycle (ram_access),
.reset_n (RESET_n),
.rw (rw_sync[1]),
.clk (MEMCLK),
.cke (CKE),
.ba (BA),
.maddr (MA),
.cas_n (CAS_n),
.ras_n (RAS_n),
.cs_n (RAMCS_n),
.we_n (MEMW_n),
.dqml (DQML),
.dqmh (DQMH),
.dtack (ram_dtack),
.eclk (ECLK),
.init_done (ram_ready)
);
IDE IDE (
.addr (ADDR[23:12]),
.din (DBUS[15:12]),
.dout (ideregister_dout),
.z2_state (z2_state),
.rw (RW),
.ds_n (uds_n_sync[1]),
.as_n (as_n_sync[1]),
.clk (MEMCLK),
.idecs1_n (IDECS1_n),
.idecs2_n (IDECS2_n),
.ide_access (ide_access),
.ide_enable (IDE_ENABLE),
.ide_enabled (ide_enabled),
.reset_n (RESET_n),
.iow_n (IOW_n),
.ior_n (IOR_n),
.rom_bank (ROM_BANK),
.ide_romen (IDE_ROMEN),
.idereg_access (idereg_access),
.otherram_en (otherram_en),
.enable_maprom (enable_maprom),
.dtack (idereg_dtack)
);
assign bonus_en = otherram_en && ovr_detect;
wire buf_en = (!UDS_n || !LDS_n || !RW);
assign RAMOE_n = !(ram_access && RESET_n && buf_en);
assign IDEBUF_OE = !(ide_access && ide_enabled && ADDR[16:15] == 2'b00 && buf_en);
wire [3:0] dout = (autoconfig_cycle) ? autoconfig_dout : ideregister_dout;
assign DBUS[15:12] = ((autoconfig_cycle || idereg_access) && RW && !uds_n_sync[1] && RESET_n) ? dout : 4'bZ;
assign OVR_n = (ram_access && ovr_detect) ? 1'b0 : 1'bZ;
assign DTACK_n = (ram_ready && ram_access && !AS_n && ovr_detect) ? 1'b0 : 1'bZ;
endmodule