We are currently in the process of converting the website to the new design. Some pages, like this one, are still broken. We appreciate your patience.
Bitwise»Episode Guide
Sequential Logic, Part 2
?
?

Keyboard Navigation

Global Keys

[, < / ], > Jump to previous / next episode
W, K, P / S, J, N Jump to previous / next marker
t / T Toggle theatre / SUPERtheatre mode
V Revert filter to original state Y Select link (requires manual Ctrl-c)

Menu toggling

q Quotes r References f Filter y Link c Credits

In-Menu Movement

a
w
s
d
h j k l


Quotes and References Menus

Enter Jump to timecode

Quotes, References and Credits Menus

o Open URL (in new tab)

Filter Menu

x, Space Toggle category and focus next
X, ShiftSpace Toggle category and focus previous
v Invert topics / media as per focus

Filter and Link Menus

z Toggle filter / linking mode

Credits Menu

Enter Open URL (in new tab)
0:08Recap and set the stage for the day continuing with sequential logic
🗩
0:08Recap and set the stage for the day continuing with sequential logic
🗩
0:08Recap and set the stage for the day continuing with sequential logic
🗩
0:46Review the off-by-one issue from yesterday, in which simulate_test() failed to update the module output values after a tick and before calling in to the tester
📖
0:46Review the off-by-one issue from yesterday, in which simulate_test() failed to update the module output values after a tick and before calling in to the tester
📖
0:46Review the off-by-one issue from yesterday, in which simulate_test() failed to update the module output values after a tick and before calling in to the tester
📖
2:18On splitting the update logic into two parts
📖
2:18On splitting the update logic into two parts
📖
2:18On splitting the update logic into two parts
📖
3:39Consult the emitted code of our entire circuit, on the update logic split between update() - computing outputs - and tick() - computing register values
🏃
3:39Consult the emitted code of our entire circuit, on the update logic split between update() - computing outputs - and tick() - computing register values
🏃
3:39Consult the emitted code of our entire circuit, on the update logic split between update() - computing outputs - and tick() - computing register values
🏃
7:52Note the fewer yields in example39_test()
📖
7:52Note the fewer yields in example39_test()
📖
7:52Note the fewer yields in example39_test()
📖
8:50Run simulate_test() successfully on example39_test
🏃
8:50Run simulate_test() successfully on example39_test
🏃
8:50Run simulate_test() successfully on example39_test
🏃
9:03Combinational pipelining
🗩
9:03Combinational pipelining
🗩
9:03Combinational pipelining
🗩
9:46Introduce delay() to construct feed-forward register chains
9:46Introduce delay() to construct feed-forward register chains
9:46Introduce delay() to construct feed-forward register chains
13:52Define Example40 module as a delay
13:52Define Example40 module as a delay
13:52Define Example40 module as a delay
15:18Check the graph of Example40, the delay
🏃
15:18Check the graph of Example40, the delay
🏃
15:18Check the graph of Example40, the delay
🏃
15:54Create simulation test for Example40
15:54Create simulation test for Example40
15:54Create simulation test for Example40
16:46Run simulate_test() successfully on example40_test
🏃
16:46Run simulate_test() successfully on example40_test
🏃
16:46Run simulate_test() successfully on example40_test
🏃
17:50A few words on the utility of delay like an operator
🗩
17:50A few words on the utility of delay like an operator
🗩
17:50A few words on the utility of delay like an operator
🗩
21:49Augmenting delay analysis to compute critical paths between internal registers
🗩
21:49Augmenting delay analysis to compute critical paths between internal registers
🗩
21:49Augmenting delay analysis to compute critical paths between internal registers
🗩
23:18Change the DelayAnalyzer use nodes rather than node names
23:18Change the DelayAnalyzer use nodes rather than node names
23:18Change the DelayAnalyzer use nodes rather than node names
29:45Run it to see our delay analysis
🏃
29:45Run it to see our delay analysis
🏃
29:45Run it to see our delay analysis
🏃
30:49Introduce combinational_multiplier() as a dumb multiplier
30:49Introduce combinational_multiplier() as a dumb multiplier
30:49Introduce combinational_multiplier() as a dumb multiplier
34:19Run simulate_test() on the combinational_multiplier() successfully
🏃
34:19Run simulate_test() on the combinational_multiplier() successfully
🏃
34:19Run simulate_test() on the combinational_multiplier() successfully
🏃
34:26Introduce pipelined_multiplier() interspersing delay() in the combinational_multiplier(), also adding an "enable" control signal in Example42
34:26Introduce pipelined_multiplier() interspersing delay() in the combinational_multiplier(), also adding an "enable" control signal in Example42
34:26Introduce pipelined_multiplier() interspersing delay() in the combinational_multiplier(), also adding an "enable" control signal in Example42
41:56Run it and hit runtime error "dictionary changed size during iteration"
🏃
41:56Run it and hit runtime error "dictionary changed size during iteration"
🏃
41:56Run it and hit runtime error "dictionary changed size during iteration"
🏃
42:10Enable linearize() to handle register discovery
42:10Enable linearize() to handle register discovery
42:10Enable linearize() to handle register discovery
44:08Run it successfully
🏃
44:08Run it successfully
🏃
44:08Run it successfully
🏃
44:13Create a test of Example42 without pipelining
44:13Create a test of Example42 without pipelining
44:13Create a test of Example42 without pipelining
45:00Run it, hit an AttributeError, and investigate the problem in register discovery
🏃
45:00Run it, hit an AttributeError, and investigate the problem in register discovery
🏃
45:00Run it, hit an AttributeError, and investigate the problem in register discovery
🏃
50:45Investigate the project in the combinational_multiplier()
50:45Investigate the project in the combinational_multiplier()
50:45Investigate the project in the combinational_multiplier()
51:39Pass through the __iter__() of SimulatorInstance while debugging
51:39Pass through the __iter__() of SimulatorInstance while debugging
51:39Pass through the __iter__() of SimulatorInstance while debugging
52:06Step through example42_test() inspecting the values
🏃
52:06Step through example42_test() inspecting the values
🏃
52:06Step through example42_test() inspecting the values
🏃
53:28Fix the "enable" control signal in Example42 to be a single bit
53:28Fix the "enable" control signal in Example42 to be a single bit
53:28Fix the "enable" control signal in Example42 to be a single bit
53:43Run simulate_test() on example42_test to completion
🏃
53:43Run simulate_test() on example42_test to completion
🏃
53:43Run simulate_test() on example42_test to completion
🏃
54:22Change pipelined_multiplier() to use the current values of x and y before reassigning them
54:22Change pipelined_multiplier() to use the current values of x and y before reassigning them
54:22Change pipelined_multiplier() to use the current values of x and y before reassigning them
56:00Run simulate_test() on example42_test, hit our test assertion and step in to pipelined_multiplier() to investigate
🏃
56:00Run simulate_test() on example42_test, hit our test assertion and step in to pipelined_multiplier() to investigate
🏃
56:00Run simulate_test() on example42_test, hit our test assertion and step in to pipelined_multiplier() to investigate
🏃
58:05Check out our generated code to see self.r8 being set incorrectly
🏃
58:05Check out our generated code to see self.r8 being set incorrectly
🏃
58:05Check out our generated code to see self.r8 being set incorrectly
🏃
59:47Change Example42 to set p and p_valid to their output() separately from the pipelined_multiplier() call
59:47Change Example42 to set p and p_valid to their output() separately from the pipelined_multiplier() call
59:47Change Example42 to set p and p_valid to their output() separately from the pipelined_multiplier() call
1:00:06Run it to see the same p_valid value as before, and check the code
🏃
1:00:06Run it to see the same p_valid value as before, and check the code
🏃
1:00:06Run it to see the same p_valid value as before, and check the code
🏃
1:01:51Scrutinise linearize() to discover the issue
📖
1:01:51Scrutinise linearize() to discover the issue
📖
1:01:51Scrutinise linearize() to discover the issue
📖
1:02:42Prevent name collision during register discovery in linearize()
1:02:42Prevent name collision during register discovery in linearize()
1:02:42Prevent name collision during register discovery in linearize()
1:06:43Realise that both update() and tick() need to use the same register names, and consider how to resolve our failure
🗩
1:06:43Realise that both update() and tick() need to use the same register names, and consider how to resolve our failure
🗩
1:06:43Realise that both update() and tick() need to use the same register names, and consider how to resolve our failure
🗩
1:07:28Make linearize() use a shared dictionary for registers
1:07:28Make linearize() use a shared dictionary for registers
1:07:28Make linearize() use a shared dictionary for registers
1:08:27Run it still unsuccessfully, with the same p_valid() value as before
🏃
1:08:27Run it still unsuccessfully, with the same p_valid() value as before
🏃
1:08:27Run it still unsuccessfully, with the same p_valid() value as before
🏃
1:08:41Make linearize() clone the counter as well
1:08:41Make linearize() clone the counter as well
1:08:41Make linearize() clone the counter as well
1:09:01Run it successfully
🏃
1:09:01Run it successfully
🏃
1:09:01Run it successfully
🏃
1:09:17Try to clean up the update_instructions and tick_instructions split in linearize()
1:09:17Try to clean up the update_instructions and tick_instructions split in linearize()
1:09:17Try to clean up the update_instructions and tick_instructions split in linearize()
1:10:55Run it and hit an AttributeError
🏃
1:10:55Run it and hit an AttributeError
🏃
1:10:55Run it and hit an AttributeError
🏃
1:12:20Revert linearize() to the working version
1:12:20Revert linearize() to the working version
1:12:20Revert linearize() to the working version
1:12:56Run simulate_test() on the real example42_test unsuccessfully, and inspect the computed values
🏃
1:12:56Run simulate_test() on the real example42_test unsuccessfully, and inspect the computed values
🏃
1:12:56Run simulate_test() on the real example42_test unsuccessfully, and inspect the computed values
🏃
1:16:56Reformulate combinational_multiplier() as a parallel assignment
1:16:56Reformulate combinational_multiplier() as a parallel assignment
1:16:56Reformulate combinational_multiplier() as a parallel assignment
1:17:51Run it to see that that works
🏃
1:17:51Run it to see that that works
🏃
1:17:51Run it to see that that works
🏃
1:17:55Change pipelined_multiplier() to use this new parallel formulation of combinational_multiplier()
1:17:55Change pipelined_multiplier() to use this new parallel formulation of combinational_multiplier()
1:17:55Change pipelined_multiplier() to use this new parallel formulation of combinational_multiplier()
1:18:54Enable delay() to handle tuples
1:18:54Enable delay() to handle tuples
1:18:54Enable delay() to handle tuples
1:19:25Run it to see it still doesn't work
🏃
1:19:25Run it to see it still doesn't work
🏃
1:19:25Run it to see it still doesn't work
🏃
1:19:28Fix pipelined_multiplier() to iterate over all the bits
1:19:28Fix pipelined_multiplier() to iterate over all the bits
1:19:28Fix pipelined_multiplier() to iterate over all the bits
1:19:33Run the pipelined multiplier successfully
🏃
1:19:33Run the pipelined multiplier successfully
🏃
1:19:33Run the pipelined multiplier successfully
🏃
1:20:21Introduce example42_test_producer() and example42_test_consumer() to give us two different agents to feed and consume from the multiplier
1:20:21Introduce example42_test_producer() and example42_test_consumer() to give us two different agents to feed and consume from the multiplier
1:20:21Introduce example42_test_producer() and example42_test_consumer() to give us two different agents to feed and consume from the multiplier
1:22:04Enable simulate_test() to handle multiple testers
1:22:04Enable simulate_test() to handle multiple testers
1:22:04Enable simulate_test() to handle multiple testers
1:24:37Run it to ensure that the existing tests do run
🏃
1:24:37Run it to ensure that the existing tests do run
🏃
1:24:37Run it to ensure that the existing tests do run
🏃
1:24:55Write a simulation test of our multiplier producer and consumer running in parallel
1:24:55Write a simulation test of our multiplier producer and consumer running in parallel
1:24:55Write a simulation test of our multiplier producer and consumer running in parallel
1:25:23Run simulate_test() on our multiplier producer and consumer, fail the test and investigate why
🏃
1:25:23Run simulate_test() on our multiplier producer and consumer, fail the test and investigate why
🏃
1:25:23Run simulate_test() on our multiplier producer and consumer, fail the test and investigate why
🏃
1:28:43Fix example42_test_consumer() to correctly yield
1:28:43Fix example42_test_consumer() to correctly yield
1:28:43Fix example42_test_consumer() to correctly yield
1:29:17Run simulate_test() on our multiplier with parallel producer and consumer successfully
🏃
1:29:17Run simulate_test() on our multiplier with parallel producer and consumer successfully
🏃
1:29:17Run simulate_test() on our multiplier with parallel producer and consumer successfully
🏃
1:29:25spriithy New place?
🗪
1:29:25spriithy New place?
🗪
1:29:25spriithy New place?
🗪
1:29:45Reflect on the utility of running more than one test co-routine at once
🗩
1:29:45Reflect on the utility of running more than one test co-routine at once
🗩
1:29:45Reflect on the utility of running more than one test co-routine at once
🗩
1:30:10Further decouple the producer and consumer using a separate "expected" queue1
1:30:10Further decouple the producer and consumer using a separate "expected" queue1
1:30:10Further decouple the producer and consumer using a separate "expected" queue1
1:33:23Run it to see that example42_test_consumer() never gets to run, and investigate why
🏃
1:33:23Run it to see that example42_test_consumer() never gets to run, and investigate why
🏃
1:33:23Run it to see that example42_test_consumer() never gets to run, and investigate why
🏃
1:35:30Run it again to see that example42_test_consumer() now gets to run
🏃
1:35:30Run it again to see that example42_test_consumer() now gets to run
🏃
1:35:30Run it again to see that example42_test_consumer() now gets to run
🏃
1:36:32Revert the decoupling
1:36:32Revert the decoupling
1:36:32Revert the decoupling
1:36:57Run it successfully
🏃
1:36:57Run it successfully
🏃
1:36:57Run it successfully
🏃
1:37:17Reflect on our pipelined system, impressing the need to keep thing in phase when mixing, and the utility of pipelining to improve the throughput of any combinational circuit
🗩
1:37:17Reflect on our pipelined system, impressing the need to keep thing in phase when mixing, and the utility of pipelining to improve the throughput of any combinational circuit
🗩
1:37:17Reflect on our pipelined system, impressing the need to keep thing in phase when mixing, and the utility of pipelining to improve the throughput of any combinational circuit
🗩
1:43:36Pipelining a 1024-bit carry-propagate adder
🗩
1:43:36Pipelining a 1024-bit carry-propagate adder
🗩
1:43:36Pipelining a 1024-bit carry-propagate adder
🗩
1:51:37That's it for the main stream
🗩
1:51:37That's it for the main stream
🗩
1:51:37That's it for the main stream
🗩