sharpie7 / circuitjs1

Electronic Circuit Simulator in the Browser
GNU General Public License v2.0
2.35k stars 642 forks source link

D-flip-flop is astable when build with subcircuits #802

Closed johndoe31415 closed 1 year ago

johndoe31415 commented 2 years ago

I'm trying to build a D-flip-flop from SR-flip-flops. I've encapsulated an SR-flipflop as a subckt:

$ 0 0.000005 10.20027730826997 50 5 50 5e-11
151 464 576 592 576 0 2 5 5
151 464 704 592 704 0 2 5 5
w 464 688 464 656 0
w 592 576 592 608 0
w 592 608 464 656 0
w 592 704 592 672 0
w 464 592 464 624 0
w 464 624 592 672 0
w 592 704 688 704 0
w 592 576 688 576 0
w 464 720 368 720 0
w 464 560 368 560 0
x 473 549 489 552 6 24 S
x 473 756 490 759 6 24 R
x 606 564 624 567 4 24 Q
x 606 692 624 695 6 24 Q
207 368 560 368 512 4 !S
207 368 720 368 672 4 !R
207 688 704 688 656 4 !Q
207 688 576 688 528 4 Q

And this is the complete D-flip-flop using the subcircuit:

$ 0 0.000005 10.20027730826997 50 5 50 5e-11
. rs_nand 0 2 2 4 !Q 1 1 3 !R 4 1 2 !S 2 0 2 Q 3 0 3 NandGateElm\s1\s2\s3\rNandGateElm\s4\s3\s1 0\\s2\\s0\\s5\s0\\s2\\s5\\s5
410 1088 -160 1184 -144 1 rs_nand 0\s2\s0\s5 0\s2\s5\s5
w 1184 80 1280 80 0
410 1088 80 1184 96 1 rs_nand 0\s2\s5\s5 0\s2\s5\s5
410 1312 -48 1408 -32 1 rs_nand 0\s2\s5\s5 0\s2\s5\s5
w 1184 -128 1280 -128 0
w 1280 -128 1280 -48 0
w 1312 -16 1280 -16 0
w 1280 -16 1280 80 0
w 1408 -48 1488 -48 0
w 1408 -16 1488 -16 0
150 944 80 1056 80 0 2 0 5
w 1056 80 1088 80 0
w 1088 112 1056 112 0
w 1056 112 1056 176 0
w 1056 176 896 176 0
w 944 96 896 96 0
w 928 -48 928 64 0
w 928 64 944 64 0
w 1088 -160 1024 -160 0
w 896 96 896 -128 0
w 896 -128 1088 -128 0
x 822 168 839 171 4 24 D
x 816 85 862 88 4 24 CLK
S 816 96 736 96 0 1 false 0 2
g 736 80 720 80 0 0
R 736 112 720 112 0 0 40 5 0 0 0.5
R 736 192 720 192 0 0 40 5 0 0 0.5
g 736 160 720 160 0 0
S 816 176 736 176 0 1 false 0 2
w 896 96 816 96 0
w 1184 112 1248 112 0
w 1024 -160 1024 -80 0
w 1024 -80 1248 32 0
w 1248 32 1248 112 0
w 896 176 816 176 0
x 1452 -58 1470 -55 4 24 Q
x 1452 15 1470 18 6 24 Q
w 1280 -48 928 -48 0
w 1280 -48 1312 -48 0

The problem is that when loading the D flip-flop, the operation becomes astable and I see constant switching between 0/1 on the Q outputs. Not sure why that would be because the SR-flipflop should be stable as-is (even for !S = !R = 0, the outputs should both be 1).

pfalstad commented 2 years ago

The problem is that if !S = !R = 1, the output is undefined unless the flip-flop is already in a stable state.

There is code to randomly pick a state if this happens. In the first circuit, you can test this by setting !S = !R = 1 and then clicking reset. It will pick a random state after a short period of oscillation. But it doesn't work in the second circuit for some reason.

johndoe31415 commented 2 years ago

Hmmm, but why is the output undefined? I agree that asserting both S and R is the illegal state, but for a given type of SR flipflop I'd argue it is well-defined: in the SR flip-flop with two NAND case, you're guaranteed that both Q and Q' become HIGH when !S = !R = 0, no matter the previous internal state. That is also required in that particular D flip-flop configuration (i.e., you could not simply change to NOR-based SR flip-flops).

In my concrete case I'm tricking my students -- and CircuitJS ;-) -- do do the right thing by applying this hacky subcircuit:

$ 0 0.000005 10.20027730826997 50 5 50 5e-11
w 928 704 1024 704 0
w 832 576 928 576 0
w 464 720 400 720 0
x 473 549 489 552 6 24 S
x 473 756 490 759 6 24 R
x 606 564 624 567 4 24 Q
x 606 692 624 695 6 24 Q
207 -32 560 -32 512 4 !S
207 -32 720 -32 672 4 !R
207 1024 704 1024 656 4 !Q
207 928 576 928 528 4 Q
w 0 720 -32 720 0
w 384 560 432 560 0
w -32 560 0 560 0
150 64 624 160 624 4 2 5 5
w 0 560 64 560 0
w 64 560 64 608 0
w 0 720 64 720 0
w 64 720 64 640 0
w 160 624 240 624 0
x 148 614 200 617 4 24 ILGL
184 288 560 320 560 0 1
w 240 624 240 672 0
w 240 672 352 672 0
w 352 656 352 672 0
R 288 592 272 592 0 0 40 5 0 0 0.5
w 64 560 288 560 0
R 304 752 288 752 0 0 40 5 0 0 0.5
184 304 720 336 720 0 1
w 240 672 240 880 0
w 240 880 368 880 0
w 368 880 368 816 0
w 304 720 64 720 0
184 736 576 768 576 0 1
184 832 704 864 704 0 1
w 592 704 832 704 0
w 368 880 800 880 0
w 896 880 896 800 0
w 800 672 800 880 0
w 800 880 896 880 0
w 592 576 736 576 0
R 736 608 720 608 0 0 40 5 0 0 0.5
R 832 736 816 736 0 0 40 5 0 0 0.5
155 480 592 528 592 14 0
w 480 656 432 656 0
w 432 656 432 560 0
w 464 720 576 720 0
w 576 720 576 656 0
w 576 624 592 624 0
w 592 624 592 704 0
w 576 592 592 592 0
w 592 592 592 576 0
g 480 624 464 624 0 0
g 480 592 464 592 0 0
pfalstad commented 2 years ago

Yes, !S = !R = 0 is fine. The problem is setting the initial state when !S = !R = 1.

Suppose Q = !Q = 0, as it is when hitting reset.

!S nand !Q = 1 !R nand Q = 1

So now Q = !Q = 1.

!S nand !Q = 0 !R nand Q = 0

So now Q = !Q = 0. Repeat forever.