feat(cpu): add A1/A2/A3 address cycle timing and fix pin propagation

This commit is contained in:
Jan-Peter von Hunnius 2026-02-24 18:58:14 +01:00
parent 3cdf99630c
commit 20884b57c3
17 changed files with 4165 additions and 270 deletions

View file

@ -46,19 +46,19 @@ impl TimingConstants {
/// This is the standard access time for ROM and RAM operations
/// based on the original Intel 4004 timing specifications.
pub const DEFAULT_ACCESS_TIME: Duration = Duration::from_nanos(500); // 500ns default
/// Fast access time for shift register operations (200ns)
///
/// The Intel 4003 shift register has faster access times compared to
/// ROM and RAM components due to its simpler design.
pub const FAST_ACCESS_TIME: Duration = Duration::from_nanos(200); // 200ns for shift registers
/// Address setup time before clock edge (100ns)
///
/// Minimum time that address must be stable before the clock edge
/// to ensure proper latching by the component.
pub const ADDRESS_SETUP: Duration = Duration::from_nanos(100); // Address setup time
/// Data valid delay after clock edge (200ns)
///
/// Time from clock edge until data is guaranteed to be valid on the bus
@ -352,19 +352,19 @@ pub enum Intel400xComponentType {
/// The 4001 is a 256-byte ROM chip that stores program instructions.
/// It responds to address transmission and provides read-only data access.
Intel4001,
/// Intel 4002 RAM (Random Access Memory) chip
///
/// The 4002 is a 320-bit RAM chip organized as four registers of 20 bits each.
/// It supports both read and write operations and includes I/O ports.
Intel4002,
/// Intel 4003 Shift Register chip
///
/// The 4003 is a 10-bit static shift register used for I/O expansion.
/// It operates differently from memory chips and ignores address transmission.
Intel4003,
/// Intel 4004 CPU (Central Processing Unit) chip
///
/// The 4004 is the 4-bit microprocessor that controls the system.
@ -383,25 +383,24 @@ pub enum Intel400xComponentType {
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Intel400xUnifiedState {
// Common states (shared across all components)
/// Idle state - component is waiting for operation
///
/// In this state, the component is not actively processing any operation
/// and is waiting for a chip select or other control signal.
Idle,
/// Address phase - latching address from CPU
///
/// The component is receiving address information in two 4-bit phases
/// (high nibble first, then low nibble) from the CPU.
AddressPhase,
/// Wait latency - waiting for access time to elapse
///
/// After receiving the complete address, the component waits for the
/// required access time before proceeding with the operation.
WaitLatency,
/// Drive data - transferring data on the bus
///
/// The component is actively driving data onto the bus (for read operations)
@ -409,21 +408,20 @@ pub enum Intel400xUnifiedState {
DriveData,
// Component-specific states
// Intel 4002 (RAM) specific states
/// Read data state - RAM is reading from memory
///
/// The RAM component is reading data from the specified address and
/// preparing to drive it onto the data bus.
ReadData,
/// Write data state - RAM is writing to memory
///
/// The RAM component is accepting data from the bus and writing it
/// to the specified memory location.
WriteData,
/// Output port state - RAM is driving I/O ports
///
/// The RAM component is outputting data to its I/O ports rather than
@ -431,13 +429,12 @@ pub enum Intel400xUnifiedState {
OutputPort,
// Intel 4003 (Shift Register) specific states
/// Shift data state - shifting register contents
///
/// The 4003 shift register is shifting its contents serially,
/// either in or out depending on the operation.
ShiftData,
/// Load data state - loading parallel data
///
/// The 4003 shift register is loading data in parallel format
@ -445,13 +442,12 @@ pub enum Intel400xUnifiedState {
LoadData,
// Intel 4004 (CPU) specific states
/// Fetch instruction state - CPU is fetching instruction
///
/// The CPU is fetching the next instruction from memory and
/// preparing to decode and execute it.
FetchInstruction,
/// Execute instruction state - CPU is executing instruction
///
/// The CPU is executing the currently fetched instruction and
@ -474,79 +470,79 @@ pub enum Intel400xEvent {
/// Generated when the first phase of the two-phase clock transitions
/// from low to high. Used for timing control in various operations.
ClockPhi1Rising,
/// Φ1 (Phase 1) clock falling edge
///
/// Generated when the first phase of the two-phase clock transitions
/// from high to low. Often triggers address latching operations.
ClockPhi1Falling,
/// Φ2 (Phase 2) clock rising edge
///
/// Generated when the second phase of the two-phase clock transitions
/// from low to high. Used for data transfer operations.
ClockPhi2Rising,
/// Φ2 (Phase 2) clock falling edge
///
/// Generated when the second phase of the two-phase clock transitions
/// from high to low. Often triggers state transitions.
ClockPhi2Falling,
/// SYNC signal becomes active (high)
///
/// The SYNC signal indicates the start of a new instruction cycle.
/// Components use this to synchronize their operations with the CPU.
SyncActive,
/// SYNC signal becomes inactive (low)
///
/// The SYNC signal indicates the end of an instruction cycle.
/// Components may use this to reset their internal state.
SyncInactive,
/// Chip select becomes active
///
/// Generated when a component is selected for an operation.
/// This typically initiates a transition from Idle to AddressPhase.
ChipSelect,
/// Chip select becomes inactive
///
/// Generated when a component is deselected.
/// This typically forces a transition back to the Idle state.
ChipDeselect,
/// RESET signal becomes active (high)
///
/// Generated when the system reset signal is asserted.
/// All components transition to their initial state.
ResetActive,
/// RESET signal becomes inactive (low)
///
/// Generated when the system reset signal is released.
/// Components begin normal operation from their reset state.
ResetInactive,
/// Address latching complete
///
/// Generated when both high and low address nibbles have been latched.
/// Triggers transition from AddressPhase to WaitLatency.
AddressComplete,
/// Access latency has elapsed
///
/// Generated when the required access time has passed after address latching.
/// Triggers transition from WaitLatency to operation-specific states.
LatencyElapsed,
/// Data is ready for transfer
///
/// Generated when data is available for reading or writing.
/// Used in component-specific data transfer operations.
DataReady,
/// Operation is complete
///
/// Generated when the current operation has finished successfully.
@ -779,22 +775,22 @@ pub trait Intel400xComponentBehavior {
pub struct Intel400xStateMachine {
/// The type of component this state machine is managing
component_type: Intel400xComponentType,
/// The current state of the state machine
pub(crate) current_state: Intel400xUnifiedState,
/// The previous state before the last transition
previous_state: Intel400xUnifiedState,
/// The high nibble (bits 7-4) of the currently latching address
address_high_nibble: Option<u8>,
/// The low nibble (bits 3-0) of the currently latching address
address_low_nibble: Option<u8>,
/// The time when the address was completely latched
address_latch_time: Option<Instant>,
/// The access time to wait after address latching before data access
access_time: Duration,
}
@ -1514,7 +1510,7 @@ mod tests {
// First need to transition to AddressPhase state
process_event_direct(&mut sm, Intel400xEvent::ChipSelect);
assert_eq!(sm.get_state(), Intel400xUnifiedState::AddressPhase);
// Now transition to WaitLatency state
process_event_direct(&mut sm, Intel400xEvent::AddressComplete);
assert_eq!(sm.get_state(), Intel400xUnifiedState::WaitLatency);