-
-
Notifications
You must be signed in to change notification settings - Fork 1
State Machines
mbtaylor1982 edited this page Nov 22, 2024
·
8 revisions
This FSM (Finite State Machine) controls the access cycles used to transfer data to and from the WDC33C93A SCSI controller. It is responsible for accessing the WDC33C93A registers and for responding to DMA cycles in coordination with the CPU FSM.
Signal | Description |
---|---|
DREQ_ | data request from SCSI chip |
FIFOFULL | FIFOCNT = 8 |
FIFOEMPTY | FIFOCNT = 0 |
BOEQ3 | byte offset = 3 |
DMADIR | DMA direction (low=write to DISK) |
CPUREQ | CPU request. Cpu wants to read/write a SCSI register |
DSACK_ | DSACK to CPU |
RIFIFO_o | Request to Increment FIFO counter (when this becomes invalid, then the increment was done) |
RDFIFO_o | Request to Decrement FIFO counter (when this becomes invalid, then the decrement was done) |
RW | Read/Write line from 68030. |
Signal | Description |
---|---|
DACK | Data Acknowledge to SCSI chip |
INCBO | increment byte offset |
INCNI | increment pointer to next longword in |
INCNO | increment pointer to next longword out |
RE | read enable to SCSI chip |
WE | write enable to SCSI chip |
SCSI_CS | Chip select to SCSI chip |
SET_DSACK | Make DSACK active |
RIFIFO_d | Request to Increment FIFO counter (out to CPU state machine) |
RDFIFO_d | Request to decrement FIFO counter (out to CPU state machine) |
S2F | Turn input buffers on so data can be read from SCSI chip (SCSI to FIFO) |
F2S | Turn output buffers on so data can be written to SCSI chip (FIFO to SCSI) |
S2CPU | Turn internal data buffers on to route data to be read from SCSI to the CPU |
CPU2S | Turn internal data buffers on to route data to be written to SCSI from the CPU |
-- |<-------- 5 clocks per byte ------- >|
-- S0,7 | S1,8 | S2,9 | S3,10 | S6,13 | S0,7 | S1,8 | S2,9 |
-- ___ ___ ___ ___ ___ ___ ___ ___
-- CPUCLK ___/ \___/ \___/ \___/ \___/ \___/ \___/ \___/
-- _____________________ ___________
-- *DREQ ___________/_________/ \_______\_________________/_________/
-- ___ _______________________ ___
-- *DSACK \_______________/ \_______________/
-- ___ _______________________ ___
-- *WE \_______________/ \_______________/
-- ___ _______________________ ___
-- *RE \_______________/ \_______________/
---
title: SCSI FSM
---
stateDiagram-v2
[*] --> IDLE_DMA_RD
IDLE_DMA_RD --> S2F_1 :SCSI to FIFO
IDLE_DMA_RD --> CPUREQ
IDLE_DMA_RD --> IDLE_DMA_WR
IDLE_DMA_RD --> IDLE_DMA_RD
IDLE_DMA_WR --> CPUREQ
IDLE_DMA_WR --> F2S_1 :FIFO to SCSI
CPUREQ --> S2C_1 :SCSI to CPU
CPUREQ --> C2S_1 :CPU to SCSI
C2S_1 --> C2S_2
C2S_2 --> C2S_3
C2S_3 --> C2S_4
C2S_4 --> C2S_5
C2S_5 --> C2S_5 : wait for DSACK
S2C_1 --> S2C_2
S2C_2 --> S2C_3
S2C_3 --> S2C_4
S2C_4 --> S2C_5
S2C_5 --> S2C_6
S2C_6 --> S2C_6 : wait for DSACK
F2S_1 --> F2S_2
F2S_2 --> F2S_3
F2S_3 --> F2S_4
F2S_4 --> IDLE_DMA_WR
S2F_1 --> S2F_2
S2F_2 --> S2F_3
S2F_3 --> S2F_4
state end <<join>>
IDLE_DMA_WR --> end
C2S_5 --> end
S2C_6 --> end
S2F_4 --> end
end --> IDLE_DMA_RD
-
s0 = IDLE_DMA_RD
-
s1 = S2F_1
-
s2 = S2F_2
-
s3 = S2F_3
-
s6 = S2F_4
-
s7 = IDLE_DMA_WR
-
s8 = F2S_1
-
s9 = F2S_2
-
s10 = F2S_3
-
s13 = F2S_4
-
s50 = CPUREQ
-
s51 = C2S_1
-
s52 = C2S_2
-
s53 = C2S_3
-
s54 = C2S_4
-
s55 = C2S_5
-
s60 = S2C_1
-
s61 = S2C_2
-
s62 = S2C_3
-
s63 = S2C_4
-
s64 = S2C_5
-
s65 = S2C_6
s0:
case (CPUREQ DREQ_ FIFOFULL DMADIR RIFIFO_o)
0 1 ? 1 ? => s0; -- no data to get.
0 0 0 1 0 => s1( RE DACK S2F); -- data ready, & room, & no incr. req. pending, so read it
0 0 0 1 1 => s0; -- data ready, and room, but increment req is pending, so wait
0 0 1 1 ? => s0; -- data ready, but no place to put it.
0 ? ? 0 ? => s7; -- go to DMA write mode
1 ? ? ? ? => s50; -- CPU wants access to a SCSI register
endcase => ANY;
s1:
if FIFOFULL then s2 (INCNI INCNO) -- This can NEVER happen! It is here to keep INCNI/RIFIFO_d & INCNO/RDFIFO_d -- output logic different (gfl to dfd converter would eliminate one).
else s2(RE DACK S2F); -- RE to scsi chip (This is the only line really necessary)
-- NOTE: Ending edge of RE is used to latch data in. SCSI spec says that it holds
-- read data valid for min of 5 nsecs, which SHOULD be enough hold time to latch it in.
-- Also, ensure BYTE OFFSET ptr & NEXT IN ptr don't change before data is latched in.
s2:
goto s3(S2F);
s3:
if BOEQ3 then s6(RIFIFO_d INCBO INCNI) -- if last byte in lword, increment the pointer
else s6(INCBO);
s6:
goto s0;
s7:
case (CPUREQ DREQ_ FIFOEMPTY DMADIR RDFIFO_o)
0 1 ? 0 ? => s7; -- SCSI chip doesn't want data yet.
0 0 1 0 ? => s7; -- SCSI ready for data, but nothing in FIFO yet.
0 0 0 0 0 => s8(DACK WE F2S); -- Data to send to SCSI, & no decrement pending, so send it
0 0 0 0 1 => s7; -- Data to send to SCSI, but decrement is pending, so wait
0 ? ? 1 ? => s0; -- go to DMA read mode
1 ? ? ? ? => s50; -- CPU wants access to a SCSI register
endcase => ANY;
s8:
goto s9(DACK WE F2S);
s9:
goto s10(F2S);
s10:
if BOEQ3 then s13(RDFIFO_d INCBO INCNO) -- if last byte in lword, increment the pointer
else s13(INCBO);
s13:
goto s7;
s50:
case (RW)
0 => s51(SCSI_CS WE CPU2S); -- Write to SCSI chip register.
1 => s60(SCSI_CS RE S2CPU); -- Read from SCSI chip register.
endcase => ANY;
s51:
goto s52(SCSI_CS WE CPU2S); -- Write to SCSI register
s52:
goto s53(SCSI_CS WE CPU2S);
s53:
goto s54(SCSI_CS CPU2S SET_DSACK);
s54:
goto s55;
s55:
if NOT DSACK_ then s55 -- Wait for write cycle to finish
else s0;
s60:
goto s61(SCSI_CS RE S2CPU); -- Read from SCSI register
s61:
goto s62(SCSI_CS RE S2CPU); -- Read from SCSI register
s62:
goto s63(SCSI_CS RE S2CPU); -- Read from SCSI register
s63:
goto s64(SCSI_CS RE S2CPU SET_DSACK);
s64:
goto s65( S2CPU );
s65:
if NOT DSACK_ then s65(S2CPU) -- Wait for read cycle to finish
else s0;