Skip to content

Commit 06f700f

Browse files
committed
Add Mermaid diagrams to 14 READMEs for complex designs
- FSMs: Mealy FSM, Divisible by 3/5, Stopwatch Timer, Sequence Detector - Serial/Parallel: Serialiser, Deserialiser - Arithmetic: Ripple Carry Adder, Carry Select Adder, ALU - Memory: Multi-Bit FIFO (state + data flow) - Advanced: LFSR, Bubble Sort, Edge Detector Diagrams visualize state machines, data flow, timing, and architecture
1 parent 33bf29c commit 06f700f

14 files changed

Lines changed: 676 additions & 0 deletions

File tree

ip/06_Edge_Detector/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,56 @@ Bonus - can you enhance your design to pulse `dout` on the same cycle as the ris
2828
Rising edge detector that registers the previous input value each clock cycle and outputs a single-cycle pulse when `din='1'` and differs from the registered value.
2929
The comparison `din /= din_reg` detects the transition, while the `din = '1'` check ensures it's specifically a rising edge.
3030

31+
### Operation Diagram
32+
33+
```mermaid
34+
flowchart LR
35+
subgraph "Clock Cycle N"
36+
din[din current] --> compare{din = 1<br/>AND<br/>din ≠ din_reg?}
37+
din_reg[din_reg<br/>previous value] --> compare
38+
compare -->|yes| pulse[dout = 1<br/>PULSE!]
39+
compare -->|no| zero[dout = 0]
40+
end
41+
42+
subgraph "Next Cycle"
43+
din --> reg[Register]
44+
reg --> din_reg_next[din_reg ← din]
45+
end
46+
47+
style pulse fill:#ffe1e1
48+
style zero fill:#ffe1e1
49+
style din fill:#e1f5ff
50+
```
51+
52+
### Timing Example
53+
54+
```mermaid
55+
%%{init: {'theme':'base'}}%%
56+
gantt
57+
title Edge Detection Timing
58+
dateFormat X
59+
axisFormat %L
60+
61+
section din
62+
Low :0, 3
63+
Rising Edge :milestone, 3, 3
64+
High :3, 5
65+
Falling Edge :milestone, 5, 5
66+
Low :5, 7
67+
68+
section din_reg
69+
Low :0, 4
70+
High :4, 6
71+
Low :6, 7
72+
73+
section dout
74+
Low :0, 4
75+
Pulse :crit, 4, 5
76+
Low :5, 7
77+
```
78+
79+
**Detection Logic:** `dout = (din AND (din XOR din_reg))` → True only on 0→1 transition.
80+
3181
---
3282

3383
## Source

ip/07_Serialiser/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,39 @@ Serializer that captures a parallel input word when `din_en` asserts and shifts
3939
A `bit_index` counter tracks which bit to output, incrementing from 0 to `DATA_WIDTH-1`.
4040
The captured data remains in `din_reg` until the entire word is transmitted, then zeros out.
4141

42+
### Operation Diagram
43+
44+
```mermaid
45+
flowchart TD
46+
Start([Start]) --> Reset{resetn?}
47+
Reset -->|active| Zero[dout = 0<br/>din_reg = 0<br/>bit_index = 0]
48+
Reset -->|inactive| CheckEn{din_en?}
49+
50+
CheckEn -->|yes| Capture[Capture din<br/>din_reg ← din<br/>bit_index = 0]
51+
CheckEn -->|no| CheckIndex{bit_index <<br/>DATA_WIDTH?}
52+
53+
Capture --> OutputBit[dout ← din_reg bit_index]
54+
55+
CheckIndex -->|yes| OutputBit
56+
CheckIndex -->|no| OutputZero[dout ← 0]
57+
58+
OutputBit --> Increment[bit_index++]
59+
OutputZero --> NextCycle([Next Clock Cycle])
60+
Increment --> NextCycle
61+
62+
NextCycle --> Reset
63+
64+
style Capture fill:#e1f5ff
65+
style OutputBit fill:#ffe1e1
66+
style OutputZero fill:#ffe1e1
67+
```
68+
69+
**Timing:**
70+
71+
- Cycle 0: `din_en=1` captures parallel word → outputs bit 0
72+
- Cycle 1-N: Shifts out bits 1 through DATA_WIDTH-1
73+
- Cycle N+1: All bits sent, outputs 0
74+
4275
---
4376

4477
## Source

ip/08_Deserialiser/README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,43 @@ Deserialiser that reconstructs a parallel word from serial input.
3434
Each clock cycle shifts the output register left and inserts the new `din` bit at the LSB position using the concatenation `dout <= dout(dout'high - 1 downto 0) & din`.
3535
After `DATA_WIDTH` clock cycles, the complete word appears at the output.
3636

37+
### Operation Diagram
38+
39+
```mermaid
40+
flowchart LR
41+
subgraph "Clock Cycle N"
42+
direction TB
43+
din[din] --> shift[Shift Left]
44+
dout_old[dout old] --> shift
45+
shift --> dout_new[dout new]
46+
end
47+
48+
subgraph "Bit Packing (LSB first)"
49+
direction LR
50+
bit0[Cycle 0<br/>din → bit 0] --> bit1[Cycle 1<br/>din → bit 1]
51+
bit1 --> bit2[Cycle 2<br/>din → bit 2]
52+
bit2 --> bitN[...<br/>Cycle N-1<br/>din → bit N-1]
53+
end
54+
55+
subgraph "Output Word"
56+
direction LR
57+
msb[MSB<br/>oldest bit] -.-> mid[...] -.-> lsb[LSB<br/>newest bit]
58+
end
59+
60+
style din fill:#e1f5ff
61+
style dout_new fill:#ffe1e1
62+
```
63+
64+
**Shift Register Operation:**
65+
66+
```flow
67+
Cycle 0: dout = 0000_0000, din=1 → dout = 0000_0001
68+
Cycle 1: dout = 0000_0001, din=0 → dout = 0000_0010
69+
Cycle 2: dout = 0000_0010, din=1 → dout = 0000_0101
70+
Cycle 3: dout = 0000_0101, din=0 → dout = 0000_1010
71+
...
72+
```
73+
3774
---
3875

3976
## Source

ip/14_Stopwatch_Timer/README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,49 @@ The `start_reg` variable latches the start condition, continuing the count until
3535
When the counter reaches MAX, it wraps to zero.
3636
The start signal acts as a sticky enable - once asserted, counting continues autonomously until explicitly stopped.
3737

38+
### State Diagram
39+
40+
```mermaid
41+
stateDiagram-v2
42+
[*] --> RESET: reset=1
43+
44+
RESET --> STOPPED: reset=0
45+
46+
STOPPED --> COUNTING: start_in=1
47+
STOPPED --> RESET: reset=1
48+
49+
COUNTING --> COUNTING: count++<br/>(wrap at MAX)
50+
COUNTING --> STOPPED: stop_in=1
51+
COUNTING --> RESET: reset=1
52+
53+
note right of RESET
54+
count_out = 0
55+
start_reg = 0
56+
Priority: Highest
57+
end note
58+
59+
note right of STOPPED
60+
count_out = frozen
61+
start_reg = 0
62+
Waiting for start
63+
end note
64+
65+
note right of COUNTING
66+
count_out increments
67+
each clock cycle
68+
start_reg = 1
69+
end note
70+
```
71+
72+
**Control Priority:** `reset` > `stop_in` > `start_in`
73+
74+
**Operation:**
75+
76+
- `start_in` latches into `start_reg` (sticky enable)
77+
- Once started, counting continues automatically
78+
- `stop_in` clears `start_reg` to halt counting
79+
- Counter wraps to 0 when reaching MAX
80+
3881
---
3982

4083
## Source

ip/15_Sequence_Detector/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,56 @@ Parameterizable sequence detector using a shift register matched against a const
2929
Each clock shifts the serial input `din` into the register, with the code handling both ascending and descending bit orderings via compile-time selection.
3030
Detection pulses high when the shift register contents exactly match `SEQUENCE_PATTERN`.
3131

32+
### State Diagram (for pattern "1010")
33+
34+
```mermaid
35+
stateDiagram-v2
36+
[*] --> IDLE: reset
37+
38+
IDLE --> SAW_1: din=1
39+
IDLE --> IDLE: din=0
40+
41+
SAW_1 --> SAW_10: din=0
42+
SAW_1 --> SAW_1: din=1
43+
44+
SAW_10 --> SAW_101: din=1
45+
SAW_10 --> IDLE: din=0
46+
47+
SAW_101 --> DETECTED: din=0<br/>dout=1 ✓
48+
SAW_101 --> SAW_1: din=1
49+
50+
DETECTED --> SAW_10: din=0
51+
DETECTED --> SAW_1: din=1
52+
53+
note right of IDLE
54+
shift_reg = xxxx
55+
No match yet
56+
end note
57+
58+
note right of SAW_1
59+
shift_reg = xxx1
60+
Partial match: "1"
61+
end note
62+
63+
note right of SAW_10
64+
shift_reg = xx10
65+
Partial match: "10"
66+
end note
67+
68+
note right of SAW_101
69+
shift_reg = x101
70+
Partial match: "101"
71+
end note
72+
73+
note right of DETECTED
74+
shift_reg = 1010
75+
FULL MATCH!
76+
dout pulses high
77+
end note
78+
```
79+
80+
**Implementation:** Shift register continuously shifts `din` in, comparator checks if register equals `SEQUENCE_PATTERN` ("1010").
81+
3282
---
3383

3484
## Source

ip/16_Divisible_by_3/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,51 @@ Exploits the property that powers of 2 modulo 3 alternate between 1 and 2 (2^0
3434
The state machine tracks remainder {0,1,2} as each bit arrives, with state transitions encoding how each bit contributes to the running modulo-3 sum.
3535
Divisible when final state is `rem_0`.
3636

37+
### State Diagram
38+
39+
```mermaid
40+
stateDiagram-v2
41+
[*] --> rem_0: reset
42+
43+
rem_0 --> rem_0: din=0<br/>dout=1
44+
rem_0 --> rem_1: din=1<br/>dout=0
45+
46+
rem_1 --> rem_2: din=0<br/>dout=0
47+
rem_1 --> rem_0: din=1<br/>dout=1
48+
49+
rem_2 --> rem_1: din=0<br/>dout=0
50+
rem_2 --> rem_2: din=1<br/>dout=0
51+
52+
note right of rem_0
53+
Remainder = 0
54+
Divisible by 3!
55+
dout = 1
56+
end note
57+
58+
note right of rem_1
59+
Remainder = 1
60+
Not divisible
61+
dout = 0
62+
end note
63+
64+
note right of rem_2
65+
Remainder = 2
66+
Not divisible
67+
dout = 0
68+
end note
69+
```
70+
71+
**State Transition Logic:**
72+
73+
- When `din=0`: Left-shift the value (multiply by 2)
74+
- rem_0 → rem_0: `(0×2) mod 3 = 0`
75+
- rem_1 → rem_2: `(1×2) mod 3 = 2`
76+
- rem_2 → rem_1: `(2×2) mod 3 = 1`
77+
- When `din=1`: Left-shift and add 1 (multiply by 2, add 1)
78+
- rem_0 → rem_1: `(0×2+1) mod 3 = 1`
79+
- rem_1 → rem_0: `(1×2+1) mod 3 = 0`
80+
- rem_2 → rem_2: `(2×2+1) mod 3 = 2`
81+
3782
---
3883

3984
## Source

ip/17_Divisible_by_5/README.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,62 @@ Powers of 2 modulo 5 cycle as {1,2,4,3,1...}, which the state machine tracks acr
3434
Each input bit transitions the state according to its positional contribution modulo 5.
3535
Divisible when final state is `rem_0`.
3636

37+
### State Diagram
38+
39+
```mermaid
40+
stateDiagram-v2
41+
[*] --> rem_0: reset
42+
43+
rem_0 --> rem_0: din=0<br/>dout=1
44+
rem_0 --> rem_1: din=1<br/>dout=0
45+
46+
rem_1 --> rem_2: din=0<br/>dout=0
47+
rem_1 --> rem_3: din=1<br/>dout=0
48+
49+
rem_2 --> rem_4: din=0<br/>dout=0
50+
rem_2 --> rem_0: din=1<br/>dout=1
51+
52+
rem_3 --> rem_1: din=0<br/>dout=0
53+
rem_3 --> rem_2: din=1<br/>dout=0
54+
55+
rem_4 --> rem_3: din=0<br/>dout=0
56+
rem_4 --> rem_4: din=1<br/>dout=0
57+
58+
note right of rem_0
59+
Remainder = 0
60+
Divisible by 5!
61+
dout = 1
62+
end note
63+
64+
note right of rem_1
65+
Remainder = 1
66+
Not divisible
67+
end note
68+
69+
note right of rem_2
70+
Remainder = 2
71+
Not divisible
72+
end note
73+
74+
note right of rem_3
75+
Remainder = 3
76+
Not divisible
77+
end note
78+
79+
note right of rem_4
80+
Remainder = 4
81+
Not divisible
82+
end note
83+
```
84+
85+
**Powers of 2 mod 5 cycle:** {1, 2, 4, 3, 1, 2, 4, 3, ...}
86+
87+
- 2^0 mod 5 = 1
88+
- 2^1 mod 5 = 2
89+
- 2^2 mod 5 = 4
90+
- 2^3 mod 5 = 3
91+
- 2^4 mod 5 = 1 (cycle repeats)
92+
3793
---
3894

3995
## Source

0 commit comments

Comments
 (0)