feat(cpu): add A1/A2/A3 address cycle timing and fix pin propagation
This commit is contained in:
parent
3cdf99630c
commit
20884b57c3
17 changed files with 4165 additions and 270 deletions
|
|
@ -391,11 +391,12 @@ impl Intel4001 {
|
|||
/// Hardware: Φ1 high = CPU drives bus with address/control information
|
||||
/// Memory operations start when SYNC goes high during Φ1 rising edge
|
||||
/// Focus: Address latching, reset, I/O operations
|
||||
///
|
||||
/// Intel 4004 Address Timing (CPU drives address during PHI1):
|
||||
/// - A1 cycle: CPU drives PC high nibble on PHI1 rising
|
||||
/// - A2 cycle: CPU drives PC low nibble on PHI1 rising
|
||||
/// - ROM latches each nibble when it sees them on the bus during AddressPhase
|
||||
fn handle_phi1_rising(&mut self) {
|
||||
println!(
|
||||
"DEBUG: [ROM] Φ1 rising edge detected, current state: {:?}",
|
||||
self.state_machine.get_state()
|
||||
);
|
||||
// Handle system reset first (highest priority)
|
||||
self.handle_reset("RESET");
|
||||
|
||||
|
|
@ -407,17 +408,23 @@ impl Intel4001 {
|
|||
let sync = self.read_sync_pin();
|
||||
let chip_select = self.read_cm_rom_pin();
|
||||
let io_select = self.read_ci_pin();
|
||||
println!(
|
||||
"DEBUG: [ROM] Φ1 rising - SYNC: {}, CM: {}, CI: {}",
|
||||
sync, chip_select, io_select
|
||||
);
|
||||
|
||||
if sync && chip_select && !io_select {
|
||||
// Start memory address phase on Φ1 rising edge (ROM access)
|
||||
// Only start a new memory operation if we're currently idle
|
||||
if self.state_machine.get_state() == Intel400xUnifiedState::Idle {
|
||||
self.process_chip_select();
|
||||
println!("DEBUG: [ROM] Starting memory operation");
|
||||
}
|
||||
|
||||
// CRITICAL: Latch address nibbles during PHI1 when CPU is driving them
|
||||
// The CPU drives address nibbles on PHI1 rising, so we must latch here
|
||||
if self.state_machine.get_state() == Intel400xUnifiedState::AddressPhase {
|
||||
let nibble = self.read_data_bus() & 0x0F;
|
||||
|
||||
if self.state_machine.handle_address_nibble(nibble) {
|
||||
// Address is complete (both nibbles latched), transition to latency wait
|
||||
self.process_address_complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -440,10 +447,6 @@ impl Intel4001 {
|
|||
/// Hardware: Φ2 high = Peripherals drive bus with data
|
||||
/// Focus: Data driving operations
|
||||
fn handle_phi2_rising(&mut self) {
|
||||
println!(
|
||||
"DEBUG: [ROM] Φ2 rising edge detected, current state: {:?}",
|
||||
self.state_machine.get_state()
|
||||
);
|
||||
// Execute current state logic
|
||||
self.execute_state_machine();
|
||||
}
|
||||
|
|
@ -453,10 +456,6 @@ impl Intel4001 {
|
|||
/// Data is held on bus during Φ2 high, tri-stated when Φ2 falls
|
||||
/// Focus: Clean up and return to idle state
|
||||
fn handle_phi2_falling(&mut self) {
|
||||
println!(
|
||||
"DEBUG: [ROM] Φ2 falling edge detected, current state: {:?}",
|
||||
self.state_machine.get_state()
|
||||
);
|
||||
match self.state_machine.get_state() {
|
||||
Intel400xUnifiedState::DriveData => {
|
||||
// End of data phase - tri-state bus and return to idle
|
||||
|
|
@ -629,10 +628,6 @@ impl Intel4001 {
|
|||
/// Focus: Address latching and setup operations
|
||||
#[allow(dead_code)] // This method is kept for compatibility but not currently used
|
||||
fn handle_memory_address_operations(&mut self) {
|
||||
println!(
|
||||
"DEBUG: handle_memory_address_operations called, current state: {:?}",
|
||||
self.state_machine.get_state()
|
||||
);
|
||||
match self.state_machine.get_state() {
|
||||
Intel400xUnifiedState::Idle => {
|
||||
// In idle state, ensure bus is tri-stated
|
||||
|
|
@ -706,10 +701,6 @@ impl Intel4001 {
|
|||
/// Handle address nibble latching during address phase
|
||||
/// Hardware: CPU provides 8-bit address as two 4-bit nibbles
|
||||
fn handle_address_latching(&mut self) {
|
||||
println!(
|
||||
"DEBUG: handle_address_latching called, current state: {:?}",
|
||||
self.state_machine.current_state
|
||||
);
|
||||
// Use common address latching functionality
|
||||
let nibble = self.read_data_bus() & 0x0F; // Only 4 bits are valid for address nibbles
|
||||
|
||||
|
|
@ -723,15 +714,10 @@ impl Intel4001 {
|
|||
/// Hardware: ROM needs 500ns to access data after address is latched
|
||||
#[allow(dead_code)] // This method is kept for compatibility with legacy code
|
||||
fn handle_latency_wait(&mut self) {
|
||||
println!(
|
||||
"DEBUG: handle_latency_wait called, state: {:?}",
|
||||
self.state_machine.current_state
|
||||
);
|
||||
// This is now handled by state machine
|
||||
if self.state_machine.is_latency_elapsed() {
|
||||
// Latency elapsed, transition to data driving
|
||||
// Data will be driven on next Φ2 rising edge
|
||||
println!("DEBUG: Latency elapsed, transitioning to DriveData state");
|
||||
self.process_latency_elapsed();
|
||||
}
|
||||
}
|
||||
|
|
@ -748,23 +734,14 @@ impl Intel4001 {
|
|||
let address = self.state_machine.get_full_address().unwrap_or(0) as u16;
|
||||
if (address as usize) < self.memory.len() {
|
||||
let data = self.memory[address as usize];
|
||||
println!(
|
||||
"DEBUG: [ROM] Driving data 0x{:02X} from address 0x{:02X} onto bus",
|
||||
data, address
|
||||
);
|
||||
self.write_data_bus(data);
|
||||
// Note: Don't call return_to_idle() here - wait for Φ2 falling edge
|
||||
} else {
|
||||
// Invalid address, tri-state
|
||||
println!(
|
||||
"DEBUG: [ROM] Invalid address 0x{:02X}, tri-stating bus",
|
||||
address
|
||||
);
|
||||
self.tri_state_data_bus();
|
||||
}
|
||||
} else {
|
||||
// Address not ready, tri-state
|
||||
println!("DEBUG: [ROM] Address not ready, tri-stating bus");
|
||||
self.tri_state_data_bus();
|
||||
}
|
||||
}
|
||||
|
|
@ -849,9 +826,7 @@ impl Component for Intel4001 {
|
|||
/// Main update cycle - handles clock edge detection and operation dispatch
|
||||
/// Hardware: Responds to Φ1 and Φ2 clock edges from CPU
|
||||
fn update(&mut self) {
|
||||
println!("DEBUG: Update called");
|
||||
if !self.is_running() {
|
||||
println!("DEBUG: Component not running, returning");
|
||||
return;
|
||||
}
|
||||
// Handle both rising and falling edges for proper two-phase operation
|
||||
|
|
@ -869,7 +844,6 @@ impl Component for Intel4001 {
|
|||
let mut events = Vec::new();
|
||||
|
||||
if phi1_rising {
|
||||
println!("DEBUG: phi1_rising detected");
|
||||
events.push(Intel400xEvent::ClockPhi1Rising);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue