Two traffic-light lessons, compared

You gave Codex and me the same brief: 20261019_exercise.md, byte-for-byte identical in both directories. It asks for a breadboard/ site whose first lesson is the 4017 + OR-gate traffic light, in 15 sections, in English and Russian. This page reviews everything in lssk_codex/breadboard and compares it with my breadboard/m11_traffic_light.

I wrote one of the two sites. To keep this fair:

Codex was still editing while I worked. Its README, pages and Questa notes changed at 13:21–13:22; its HDL has not changed since 07:30. This review is of a snapshot taken at 13:27 PDT on 21 October. I changed nothing in lssk_codex.

The rules were not the same for both of us. Codex got yuri_rules_3.txt, with eight rules. I got yuri_rules_4.txt, which has two of them plus "Asynchronous reset is also OK". The style section checks both sites against all of the rules.

Both passCodex's three benches pass in Icarus 12 and 14, Verilator and Questa (Questa run by me with the license)
Stock Yosys: notimeunit in every RTL file: Yosys 0.69 read_verilog -sv fails on line 15. Mine synthesizes.
12/12 vs 9/12Bugs caught: Codex's three benches together vs my single bench
19 × # 1, 2 × negedgeIn Codex's benches. Mine has neither: only the clock generator has a delay.
45 vs 34 wiresCodex: 37 jumpers + 2 supply + 6 module leads. Mine: 24 jumpers + 10 module leads.
11 vs 5Mentions of Timofei on the English lesson page, counting the code

Verdict

What the tools say

CheckCodexMine
Icarus 12.0PASS: all three benches, 285 checks in the main onePASS: 82 checks
Icarus 14.0 develPASS: all threePASS
Verilator 5.053, as each script runs itPASS: all three, with --timing and without -Wall; the script turns off PINCONNECTEMPTY and DECLFILENAMEPASS with -Wall
Verilator -Wall lint
  • RTL: 4 × PINCONNECTEMPTY, from empty () pins in traffic_light_chips.sv.
  • Benches: PROCASSINIT on logic clk = 1'b0;, the very clock form that rules_3 prescribes.
  • Also DECLFILENAME on project.v, UNUSEDPARAM clk_mhz and 14 empty pins in tb_integrations.
Style warnings only; none of them is a bug.
0 warnings. My unused outputs get named wires, and two lint_off lines carry a comment.
Questa 2025.2 with the licensePASS: all three benches, 0 errors and 0 warnings. I ran Codex's 13:21 run_questa.sh from my shell. The page still tells students the simulation "is blocked". PASS: 0 errors, 0 warnings
Yosys 0.69 read_verilog -sv, which BGM's Yosys flow usesParse error: rtl/traffic_light.sv:15: ERROR: syntax error, unexpected TOK_TIME_SCALE. Yosys 0.43 gives the same error. OK:
  • traffic_light: 23 cells, 5 flip-flops.
  • traffic_light_chips: 26 cells, 5 flip-flops.
  • The TT top passes check -assert.
Yosys 0.69 + SlangOK: both cores; the TT top is 81 cellsNot needed
Wiring checkStatic checks:
  • no hole used twice, no shorts;
  • every functional pin connected, NC pins left free;
  • split rails bridged.
I checked all 37 jumpers against the chip pinouts by hand and found no error.
Static checks:
  • no hole used twice, no shorts;
  • no floating input, one driver per net.
The wire list is also simulated and must give RRRRYYGGGG.
Link check178 local links checked by its validate.py; I found no broken onesLink and anchor checks clean

Errors and wrong claims in Codex's site

Ranked by how much they would hurt a student or a teacher. "Evidence" is what I ran or read today.

#SeverityWhatEvidenceFix
1high timeunit/timeprecision in all 11 HDL files, synthesizable ones included. The TT project.v, both cores, the chip models and both BGM wrappers fail to parse with Yosys's standard reader. Codex says "the older local Yosys 0.43 built-in reader cannot parse"; the newest Yosys here fails the same way.
  • Yosys 0.69+24 and 0.43 both report unexpected TOK_TIME_SCALE.
  • BGM's scripts/steps/00_setup_yosys.source_bash runs read_verilog … -sv.
  • BGM's timeunit appears only in tb.sv files.
  • Codex's TT section admits a template "needs a frontend change".
Keep timeunit in testbenches only, as BGM does. The rule's own example was a testbench.
2medium Schematic 1 has no flip-flops and no gates for the state. It shows a "10-state cyclic FSM" box feeding three ORs. The brief asks for "gates, flip-flop and other elements in generic fashion". The generic RTL is a ring of ten flip-flops, and no drawing shows that ring. images/logic_en.svg, whose caption says "the block defines behavior, not a storage encoding" Draw the register. Either draw ten flip-flops in a ring, or, like mine, the 4017's own 5-bit Johnson counter with a 10-gate decoder.
3medium The two negedge waits are called "necessary", and they are not. The style guide says "a posedge-only reset check would not establish this behavior".
  • The real reason is Codex's own sampling scheme: @ (posedge clk); # 1. Right after the rising edge, a design that counts on the falling edge already shows the expected value, so the bench needs the negedge block to catch it.
  • For the 4017 INHIBIT test, the CLOCK pin is just an input of the device under test. The bench can drive it like any other input at rising edges of its own clock.
No need_to_deviate_from_style.html was written. validation.json says "style_deviation_required": false.
Bug hunt: with the negedge block deleted, Codex's main bench misses "counts on the falling edge". My rising-edge checker catches it. Use a BGM-style checker in always @ (posedge clk). It samples the values of the cycle that just ended.
4medium Timofei is credited too often, and as the originator.
  • Each lesson page mentions him 11 times: 6 in the text and 5 in code.
  • The code includes tt_um_timofei_traffic_light and 1_11_timofei_traffic_light.
  • Both footers and the README say "Traffic-light idea: Timofei Nikiforov".
You corrected me on exactly this: the same design was published earlier, as a 2014 B.Tech student project on SlideShare.
Visible text: title, h1, table of contents, section 1 heading, section 1 text, footer. The index page has 2 more. Drop the footer credit and the name in module names and paths. Keep one factual mention of where the circuit was described.
5low–medium The Questa status on the page is wrong for this machine. Section 11 says: "Runtime blocked here: FlexNet sees an empty host ID and Questa reports Invalid host." That is true inside Codex's sandbox only. The README says the same. Codex's own updated run_questa.sh, run from a normal shell, passes all three benches Report the real result, or leave sandbox details out of student pages.
6low–medium The lesson disagrees with Codex's own exercise list and kits. exercises.html calls the exercise P11 and uses the 5 V traffic-light module (LSSK row 64). The lesson is BB-FSM-01 and uses three separate 5 V LEDs (rows 46–48). The sheet itself notes that those three LEDs are "not really needed". lssk_codex/exercises.html, P11 entry Use the list's ID and its traffic-light module. One module GND lead replaces the three LED cathode jumpers.
7low The power module is drawn off the board, with "two supply leads" to LP01 and LM01. The part in row 56 is a breadboard power module that plugs straight into the rails. So two wires are extra, and the picture differs from the getting-started guide. Codex's parts table, the text under schematic 3, and row 56 of its saved sheet rows Plug the module into the rails at the end of the board.
8low Rail coordinates such as LP25 and RM08 are invented. Real boards print no hole numbers on the rails. The split between holes 25 and 26 is an assumption; the text admits it. Section 7 and jumpers.csv Refer to rails by the printed column numbers, the way my checklist does: "top + rail, column 12".
9low A wrong reason for leaving out `default_nettype none. The guide says "Questa rejects their implicit net types". Every tool must reject ports without a net type; that is what the directive is for. project.v also drops the TT template's `default_nettype none and its input wire header, which the brief quoted. Style guide §16 and integration/tinytapeout/project.v Keep the TT template header as given.
10low The Verilator check is weaker than it looks. The script runs without -Wall and turns off two warnings, while the page says only "All three testbenches pass". See "What the tools say" above Use named unused wires and -Wall.

Questionable design choices

Testbench and HDL style against your rules

Rules marked rules_3 only were given to Codex and not to me. I check my code against them as well, because you may want them applied to both sites.

RuleCodexMine
No # delay unless necessary both 19 sites of # 1: 9 in tb_cmos, 6 in tb_integrations, 4 in tb_traffic_light. Some sit in tasks that run hundreds of times. Only # 5 in the clock generator
No negedge unless you have to both 2 sites, both avoidable (finding 3)None
Follow the BGM examples both No always @ (posedge clk) checker, no was_reset, no final. Stimulus uses blocking assignments in the middle of the cycle, with no <= anywhere. Checker at the rising edge, was_reset, summary in final. Stimulus uses <= after @ (posedge clk).
Report deviations in need_to_deviate_from_style.html both Not written. The exceptions are explained in the style guide instead.No deviations
New SystemVerilog time syntax, not `timescale rules_3 only Done, but in every file, which breaks synthesis (finding 1) No time unit at all, so units depend on the simulator: Verilator reports $finish at 445ps, while Icarus uses its own default. Adding timeunit to tb.sv only would fix it.
wire only for wire a = …; rules_3 only Followed Three places don't follow it:
  • wire [9:0] q, q_chips; for the DUT outputs in tb.sv, which is what the BGM FIFO bench does too;
  • wire unused_4071_j; and similar in traffic_light_chips.sv;
  • wire [9:0] q; in project.v.
Align = rules_3 onlyMostlyYes
Clock in its own always # (period / 2) rules_3 only Yes. Verilator -Wall flags it as PROCASSINIT. The clock has its own initial … forever block, as in the BGM examples, but not this exact form.
Tasks without Verilog-95 begin/end rules_3 onlyYesNo tasks
Timeouts in clock cycles rules_3 only500, 500 and 200 cycles No watchdog. The run has a fixed length, so it cannot hang, but a cycle watchdog costs three lines.

Codex's style guide (22 rules, English and Russian, Markdown copies) is a good idea, and it records the upstream commits it cites. Three of its rules contradict the evidence above: §17 puts timeunit everywhere, §16 gives the wrong reason for default_nettype, and the section "Why specific # 1 and negedge uses remain" says the negedge waits are necessary.

Bug hunt: the same 12 bugs in both designs

Each bug was put into a fresh copy and run with Icarus 12. "Caught" means the bench printed no PASS. For Codex, "main without negedge" is tb_traffic_light.sv with its low-clock block deleted.

BugCodex
tb_cmos
Codex
main
Codex
integrations
Codex main
without negedge
Mine
No bug (sanity)passpasspasspasspass
Generic design counts on the falling clock edgemissedcaughtmissedmissedcaught
Generic design: synchronous resetmissedcaughtcaughtcaughtcaught
Generic design: reset goes to state 1missedcaughtcaughtcaughtcaught
Generic design: green misses state 6missedcaughtcaughtcaughtcaught
Chips: a red OR input on Q4 instead of Q3missedcaughtcaughtcaughtcaught
Chips: a green OR input left at GNDmissedcaughtcaughtcaughtcaught
4017 model: synchronous resetcaughtcaughtcaughtcaughtcaught
4017 model counts on the falling edgecaughtcaughtmissedmissedcaught
4017 model ignores CLOCK INHIBITcaughtmissedmissedmissedmissed
4017 model: CARRY high in counts 0–5caughtmissedmissedmissedmissed
4071 gate J is AND (Codex's yellow gate; unused in mine)caughtcaughtcaughtcaughtmissed
4071 gate K is AND (my yellow gate; unused in Codex's)caughtmissedmissedmissedcaught

Presentation and wording

What works well in Codex's site

  • Clean layout: a dark header with three numbers (4/2/4, 3 chips, 10 states), a sticky table of contents, and each section in its own card. A print stylesheet is included.
  • Every figure is an SVG file with SVG and PNG download links and alt text.
  • Both pages set lang and hreflang, and the two languages link to each other.
  • Seven clean drawings. The state graph has the Moore outputs inside the nodes, and a second graph shows the one-hot codes. The pinouts are clear.
  • The parts table links each part to its exact sheet row, for example range=LSSK!A37:Q37, and comes with CSV files for parts and jumpers.
  • A small JavaScript stepper (Run 1 Hz, Step, Reset) shows the ten states and the lamps. It works offline.
  • A troubleshooting table and "try next" tasks. One useful note: the source's "outputs 1–4, 5–6, 7–10" counts from one, while the datasheet says Q0–Q9.

What doesn't

  • Notes meant for you appear on student pages:
    • "the prompt's 'hackaton_top' omits an h", which also appears as a comment inside hackathon_top.sv;
    • "The live Google sheet was unavailable during this update";
    • "Icarus 13 … is not installed here";
    • the FlexNet host-ID story;
    • "fetch timed out; no technical claims rely on it";
    • "the quotation in the assignment and archived text were used".
  • The breadboard drawing is hard to follow. Ten signal wires leave the board and loop around its left side. Labels cover row numbers and pin numbers, and the clock and reset modules are not drawn. A student needs the hole-by-hole table to build it, and that table is collapsed.
  • The timing diagram is drawn by hand, not taken from the simulation. It has no reset trace. The clock starts high at t = 0, so the first counting edge is ambiguous.
  • Code has no syntax highlighting and is collapsed. There is no dark mode.
  • Calling the Habr article "Yuri Panchul's course" and listing it under "Course and the traffic-light exercise" is vague. The lesson number, 1.7, would help readers find it.

Russian page

The translation is complete and matches the English section by section. The problems are terminology and a few calques:

Ideas to adopt

From Codex into my lesson

I have not changed anything yet. Tell me which of these to do.

  1. A unit-test bench for the chip models, in the posedge style: every OR input pattern on every pin, plus the 4017's CARRY and CLOCK INHIBIT. CLOCK INHIBIT can be tested by driving CLOCK as data from the bench's clock. This closes the three bugs I miss.
  2. A simulation of the wrappers (lab_top, hackathon_top, project.v) with both designs. I have never simulated mine.
  3. A synthesis check script: Yosys read_verilog -sv; synth; check -assert, run on the stock reader.
  4. Parts linked to their sheet rows, while keeping my prices.
  5. CSV downloads for parts and wires, and a ZIP of the exercise without build logs.
  6. The note about counting from one ("outputs 1–4" are Q0–Q3).
  7. A troubleshooting table that maps each symptom to what to check.
  8. rules_3 items, if you want them in my code too:
    • timeunit 1ns; timeprecision 1ps; in tb.sv only;
    • logic for DUT outputs and unused nets;
    • a watchdog counted in clock cycles.
  9. Optional: the small state stepper widget.

From my lesson into Codex's

  1. Schematic 1 with real flip-flops and gates. The Johnson counter and decoder are what is inside the 4017.
  2. A breadboard drawing that looks like the board, with the modules on it, plus a checklist with tick boxes.
  3. A waveform made from the simulation's VCD, so the picture and the testbench cannot disagree.
  4. A rising-edge checker with was_reset and final, which removes all # 1 delays and negedge waits.
  5. RTL that the stock Yosys reader accepts, so BGM's Yosys flow and Tiny Tapeout work without Slang.
  6. The kit's traffic-light module and prices from the sheet.
  7. A clean -Wall run, syntax highlighting, copy buttons and dark mode.

The brief, item by item

Brief itemCodexMine
1 · ID, name, why it mattersBB-FSM-01, a new ID that is not the P11 in its own list. Good motivation and prerequisites.M11, the ID from exercises.html
2 · Key element, symbols, truth table, waveformFSM graph, OR truth tables, hand-drawn timing, stepper widgetThe 4017 explained, with a waveform from the simulation
3 · PartsRows of the sheet with deep links and a CSV; no prices; three separate LEDs; 37 + 2 + 6 wiresPrices and suppliers; the traffic-light module; 24 + 10 wires; no CSV
4 · Chips, pins, polarityThree pin tables and a pinout drawing. The CLOCK INHIBIT detail cites Nexperia.A pinout and table for each chip
5 · Schematic 1: flip-flops and gatesA black box and three ORs5 flip-flops, 10 ANDs and 3 ORs
6 · Schematic 2: chip connectionsClean pin-level block diagramChip-level schematic
7 · Schematic 3: breadboardHole map with all 37 jumpers; dense and abstract; the CSV and table are exactPicture of the board with the modules, build steps and a checklist with tick boxes
8 · Generic SystemVerilogA one-hot ring of ten flip-flopsA Johnson counter and decoder, matching schematic 1 and the 4017
9 · Chip modelsPorts named after pins (p14_clock); marked synthesizableDatasheet names, with the pin number in a comment; marked synthesizable
10 · Chip-level SystemVerilogGenerated from the pin and net databaseGenerated from the checked wire list
11 · Testbench for Icarus, Questa and VerilatorThree benches; scripts that accept tool paths from environment variables. The page says Questa cannot run, but it can.One bench, three scripts and a clean script; all three simulators run
12 · BGM lab_topFull interface, LEDs and LCD colour, reset on key[0], a staging scriptLEDs show a running state, the 7-segment display shows the light
13 · BGM hackathon_topFills the LCD with the current colourDraws a traffic light on the LCD
14 · Tiny Tapeout project.vUses clock_hz: 1 with no divider. A DIP switch selects bars or the state digit, and the lamps also go to uio. Needs Slang to synthesize.Uses clock_hz: 1 with no divider. Bars on the display; stock Yosys works; a comment says to rename the module.
15 · OtherBring-up steps, a troubleshooting table, "try next" tasks and sourcesTasks including a clock enable, and related designs
Site: list page, English and Russian, linkedYes, plus a style guideYes

How this was checked