Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 28 additions & 26 deletions SF2000-FW.peri.xml

Large diffs are not rendered by default.

21 changes: 20 additions & 1 deletion SF2000-FW.sdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@

# PLL Constraints
#################
#create_clock -period 70.00 C14M
create_clock -period 140.00 C7M_n

# turbo_clk (40 MHz): PLL 80 MHz / 2, drives CLKCPU in turbo mode.
# Using create_clock because Efinity cannot trace create_generated_clock
# through the global clock buffer from the PLL output to this FF.
create_clock -period 25.00 -name turbo_clk [get_pins {turbo_clk~FF|Q}]

# CDC: Three asynchronous clock domains.
# All cross-domain paths use 2-stage synchronizers — no timing analysis needed.
set_clock_groups -asynchronous \
-group {C7M_n} \
-group {turbo_clk} \
-group {pll_inst1_CLKOUT1}

# False paths: Quasi-static autoconfig registers (C7M domain)
# These only change during boot autoconfig and are completely static
# during normal operation. Eliminates false hold violations on
# base_ram/ram_configured_n → fastram OE/WE paths that waste PnR effort.
# Using get_cells -from (Efinity rejects get_pins |Q as a startpoint).
set_false_path -from [get_cells {base_ram[*]~FF}]
set_false_path -from [get_cells {ram_configured_n~FF}]
set_false_path -from [get_cells {sd_configured_n~FF}]
12 changes: 8 additions & 4 deletions SF2000-FW.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<efx:project name="SF2000-FW" description="" last_change="1768294784" sw_version="2024.2.294" last_run_state="pass" last_run_flow="bitstream" config_result_in_sync="true" design_ood="change" place_ood="sync" route_ood="sync" xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd">
<efx:project name="SF2000-FW" description="" last_change="1776539067" sw_version="2025.2.288.2.10" last_run_state="pass" last_run_flow="bitstream" config_result_in_sync="true" design_ood="change" place_ood="sync" route_ood="sync" xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd">
<efx:device_info>
<efx:family name="Trion"/>
<efx:device name="T8Q144"/>
Expand All @@ -25,9 +25,9 @@
<efx:sdc_file name="SF2000-FW.sdc"/>
<efx:inter_file name=""/>
</efx:constraint_info>
<efx:isf_info/>
<efx:sim_info/>
<efx:misc_info/>
<efx:ooc_info/>
<efx:ip_info/>
<efx:synthesis tool_name="efx_map">
<efx:param name="work_dir" value="work_syn" value_type="e_string"/>
Expand Down Expand Up @@ -64,17 +64,21 @@
<efx:param name="max_threads" value="-1" value_type="e_integer"/>
<efx:param name="mult_input_regs_packing" value="1" value_type="e_option"/>
<efx:param name="mult_output_regs_packing" value="1" value_type="e_option"/>
<efx:param name="enable-mark-debug" value="1" value_type="e_option"/>
<efx:param name="max-bit-blast-mem-size" value="10240" value_type="e_integer"/>
<efx:param name="suppress_info_msgs" value="off" value_type="e_bool"/>
<efx:param name="suppress_warning_msgs" value="off" value_type="e_bool"/>
</efx:synthesis>
<efx:place_and_route tool_name="efx_pnr">
<efx:param name="work_dir" value="work_pnr" value_type="e_string"/>
<efx:param name="verbose" value="off" value_type="e_bool"/>
<efx:param name="load_delaym" value="on" value_type="e_bool"/>
<efx:param name="optimization_level" value="NULL" value_type="e_option"/>
<efx:param name="seed" value="1" value_type="e_integer"/>
<efx:param name="placer_effort_level" value="2" value_type="e_option"/>
<efx:param name="max_threads" value="-1" value_type="e_integer"/>
<efx:param name="print_critical_path" value="10" value_type="e_integer"/>
<efx:param name="classic_flow" value="off" value_type="e_noarg"/>
<efx:param name="suppress_info_msgs" value="off" value_type="e_bool"/>
<efx:param name="suppress_warning_msgs" value="off" value_type="e_bool"/>
</efx:place_and_route>
<efx:bitstream_generation tool_name="efx_pgm">
<efx:param name="mode" value="active" value_type="e_option"/>
Expand Down
13 changes: 6 additions & 7 deletions rtl/autoconfig_zii.v
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ localparam [7:0] RAM_PROD_ID = 8'd10; // 5194/10 - SF2000, Memory Master (4M
localparam [7:0] SD_PROD_ID = 8'd11; // 5194/11 - SF2000, SD card controller I/O device (64K)
localparam [15:0] SERIAL = 16'd0;

reg [1:0] configured_n = 2'b11;
reg [1:0] configured_n = 2'b11; // Both unconfigured
reg [1:0] shutup_n = 2'b11;
reg [1:0] config_out_n = 2'b11;
reg [1:0] config_out_n = 2'b11; // Start with RAM

wire autoconfig_access = !CFGIN_n && CFGOUT_n && (A_HIGH == 8'hE8) && !AS_CPU_n;

Expand All @@ -44,15 +44,15 @@ assign SD_CONFIGURED_n = configured_n[SD_CARD];
assign CFGOUT_n = |config_out_n;
assign DATA_OE = autoconfig_access && RW_n && !DS_n;

always @(negedge RESET_n or posedge C7M) begin
always @(negedge RESET_n or posedge AS_CPU_n) begin

if (!RESET_n) begin

config_out_n <= 2'b11;
config_out_n <= 2'b11; // Start with RAM

end else begin

if (AS_CPU_n) config_out_n <= configured_n & shutup_n;
config_out_n <= configured_n & shutup_n;

end
end
Expand All @@ -61,7 +61,7 @@ always @(negedge RESET_n or posedge C7M) begin

if (!RESET_n) begin

configured_n <= 2'b11;
configured_n <= 2'b11; // Both unconfigured
shutup_n <= 2'b11;

end else begin
Expand Down Expand Up @@ -159,5 +159,4 @@ always @(negedge RESET_n or posedge C7M) begin
end
end


endmodule
23 changes: 8 additions & 15 deletions rtl/bus_arbiter.v
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,11 @@ module bus_arbiter(
);

/*
Hybrid Bus Arbiter

Takes KEY working elements from user's proven firmware:
1. BR_68SEC000_n = 0 at reset (hold 68SEC000!)
2. Fast bootstrap check (not 100 clocks)
3. Condition: (BG_n_IN != 0 || JP2 != 0)
4. BOSS_n_IN HIGH = B2000

Keeps BETTER structure from previous attempt:
1. Synchronizers for metastability protection
2. Cleaner state machine
3. Clear mode separation
Bus Arbiter

Detects machine type (A2000 vs B2000) and CPU presence at boot.
Manages 3-way bus arbitration between 68SEC000, internal 68000, and
external DMA masters. All external signals use 2-stage synchronizers.
*/

//=============================================================================
Expand Down Expand Up @@ -197,10 +190,10 @@ always @(posedge C7M) begin
if (dma_en) begin
// Mode 1 or Mode 3: DMA enabled
BR_n_OE <= 1'b0; // Don't drive BR to internal CPU
BR_68SEC000_n <= BR_n_IN & BGACK_n; // 3-to-2 mapping (your elegant formula!)
BR_68SEC000_n <= br_n_in_sync[1] & bgack_sync[1]; // 3-to-2 mapping (synced)

BG_n_OE <= 1'b1; // Drive BG to external DMA
BG_n_OUT <= BG_68SEC000_n; // Pass through 68SEC000's BG
BG_n_OUT <= bg_68sec_sync[1]; // Pass through 68SEC000's BG (synced — CDC from 25MHz)

end else begin
// Mode 2: A500 with CPU, no DMA
Expand Down
57 changes: 34 additions & 23 deletions rtl/fastram.v
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

module fastram(
input wire CLKCPU,
input wire BGACK_n,
input wire CPU_SPEED_SWITCH,
input wire [23:21] A,
input wire JP4,
Expand All @@ -27,15 +28,8 @@ module fastram(
/*
Fast RAM Controller - Conditional Registered OE/WE

KEY INSIGHT:
- At 7 MHz: Combinatorial OE/WE works fine (always worked!)
- At turbo: Need registered OE/WE for longer write pulses (stable writes)

Solution: Use registered OE/WE only at turbo speeds!

This way:
- 7 MHz: Fast, combinatorial (DMA/HCII+8 works) ✅
- Turbo: Registered negedge WE (stable, reliable writes) ✅
7 MHz: Combinatorial OE/WE (fast, DMA-compatible).
Turbo: Registered OE/WE on negedge for longer write pulses.
*/

/*
Expand All @@ -53,6 +47,22 @@ wire second_4MB_access = !AS_n && !RAM_CONFIGURED_n && JP4 && ( (A == (BASE_RAM

assign RAM_ACCESS = JP4 ? (first_4MB_access || second_4MB_access) : first_4MB_access;

// Filter address glitches during external DMA.
// Address transitions can transiently match the SRAM range, causing
// OE/WE to glitch. Requires 1-clock address stability before enabling.
reg dma_ram_valid;
always @(posedge CLKCPU) begin
if (AS_n)
dma_ram_valid <= 1'b0;
else
dma_ram_valid <= RAM_ACCESS;
end

// Gate for combinatorial OE/WE:
// If DMA (!BGACK_n), requires 1-clock stability to prevent address glitches.
// If CPU (BGACK_n), bypasses filter for 0-wait-state performance.
wire safe_to_enable = BGACK_n ? 1'b1 : dma_ram_valid;

//=============================================================================
// Registered OE/WE Signals (for turbo mode)
//=============================================================================
Expand All @@ -65,7 +75,7 @@ reg WE_BANK0_EVEN_n_reg = 1'b1;
reg WE_BANK1_EVEN_n_reg = 1'b1;

// OE registered on posedge
always @(posedge CLKCPU or posedge AS_n) begin
always @(posedge CLKCPU) begin
if (AS_n) begin
OE_BANK0_n_reg <= 1'b1;
OE_BANK1_n_reg <= 1'b1;
Expand All @@ -76,7 +86,7 @@ always @(posedge CLKCPU or posedge AS_n) begin
end

// WE registered on negedge (for maximum write time)
always @(negedge CLKCPU or posedge AS_n) begin
always @(negedge CLKCPU) begin
if (AS_n) begin
WE_BANK0_ODD_n_reg <= 1'b1;
WE_BANK1_ODD_n_reg <= 1'b1;
Expand All @@ -94,14 +104,14 @@ end
// Combinatorial OE/WE Signals (for 7 MHz mode)
//=============================================================================

wire OE_BANK0_n_comb = first_4MB_access && RW_n && !DS_n ? 1'b0 : 1'b1;
wire OE_BANK1_n_comb = second_4MB_access && RW_n && !DS_n ? 1'b0 : 1'b1;
wire OE_BANK0_n_comb = first_4MB_access && safe_to_enable && RW_n && !DS_n ? 1'b0 : 1'b1;
wire OE_BANK1_n_comb = second_4MB_access && safe_to_enable && RW_n && !DS_n ? 1'b0 : 1'b1;

wire WE_BANK0_ODD_n_comb = first_4MB_access && !RW_n && !LDS_n ? 1'b0 : 1'b1;
wire WE_BANK1_ODD_n_comb = second_4MB_access && !RW_n && !LDS_n ? 1'b0 : 1'b1;
wire WE_BANK0_ODD_n_comb = first_4MB_access && safe_to_enable && !RW_n && !LDS_n ? 1'b0 : 1'b1;
wire WE_BANK1_ODD_n_comb = second_4MB_access && safe_to_enable && !RW_n && !LDS_n ? 1'b0 : 1'b1;

wire WE_BANK0_EVEN_n_comb = first_4MB_access && !RW_n && !UDS_n ? 1'b0 : 1'b1;
wire WE_BANK1_EVEN_n_comb = second_4MB_access && !RW_n && !UDS_n ? 1'b0 : 1'b1;
wire WE_BANK0_EVEN_n_comb = first_4MB_access && safe_to_enable && !RW_n && !UDS_n ? 1'b0 : 1'b1;
wire WE_BANK1_EVEN_n_comb = second_4MB_access && safe_to_enable && !RW_n && !UDS_n ? 1'b0 : 1'b1;

//=============================================================================
// Output Mux: Registered at turbo, Combinatorial at 7 MHz
Expand All @@ -120,20 +130,21 @@ assign WE_BANK1_EVEN_n = CPU_SPEED_SWITCH ? WE_BANK1_EVEN_n_reg : WE_BANK1_EVEN_
// DTACK Generation
//=============================================================================

reg [2:0] wait_counter;
wire [2:0] wait_states = CPU_SPEED_SWITCH ? 3'd0 : 3'd0;
reg [3:0] wait_counter;
// DMA: 6 wait states for expansion card stability. CPU: 0 wait states.
wire [3:0] wait_states = (!BGACK_n) ? 4'd6 : 4'd0;

always @(posedge CLKCPU or posedge AS_CPU_n) begin
always @(posedge CLKCPU) begin

if (AS_CPU_n) begin
if (AS_n) begin
DTACK_n <= 1'b1;
wait_counter <= 3'd0;
wait_counter <= 4'd0;
end else begin

if (RAM_ACCESS) begin
if (wait_counter < wait_states) begin
DTACK_n <= 1'b1;
wait_counter <= wait_counter + 3'd1;
wait_counter <= wait_counter + 4'd1;
end else begin
DTACK_n <= 1'b0;
end
Expand Down
2 changes: 1 addition & 1 deletion rtl/flash.v
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ assign FLASH_ACCESS = A[23:20] == 4'hA && !maprom_enabled || /
A[23:19] == 5'b11111 && maprom_enabled || // $F80000-FFFFFF
A[23:19] == 5'b11100 && maprom_enabled; // $E00000-E7FFFF

always @(posedge CLKCPU or posedge AS_CPU_n) begin
always @(posedge CLKCPU) begin

if (AS_CPU_n) begin
DTACK_n <= 1'b1;
Expand Down
Loading