CSCE 611 Fall 2026 Lecture 6: Even more SystemVerilog
Watch on YouTube →
Overview
Jason D. Bakos reviews RISC-V and SystemVerilog quiz concepts, then connects structural HDL, signal driving, and FPGA lab setup to simulation and behavioral coding. The lecture develops SystemVerilog test benches and explains `initial`, `always_comb`, `always_ff`, sensitivity lists, latch inference, flip-flops, and self-checking tests for the seven-segment-decoder labs.
Key takeaways
- For a RISC-V loop over four-byte integers, an element bound of 10 corresponds to a 40-byte offset when the loop counter is also used for address calculation.
- SystemVerilog's four-state `logic` values distinguish known `0` and `1` from unknown or conflicting `X` and high-impedance `Z`; conflicting active drivers can produce `X` in simulation.
- `always_comb` blocks must assign every output on every possible control path; a missing assignment makes synthesis infer storage such as a latch.
- Use `always_ff` with a clock edge for flip-flop-based sequential logic, and prefer edge-triggered registers over latches because they are easier to analyze for timing.
- A self-checking test bench combines input stimulus, a short settling delay or clock phase, and output comparisons so repeated simulation runs can detect failures automatically.
- The Lab 2 seven-segment decoder work is reused in Lab 3, where a CPU replaces the direct switch-to-decoder connection and processes the same FPGA inputs and displays.
Chapters
0:00
RISC-V Loop Translation and the Missing Branch Condition
- The C loop uses an array of four-byte integers, so its assembly loop limit is 40 bytes rather than 10 elements.
- Registers hold the array base, loop index, temporary addresses, and loaded values; the missing instruction checks whether the index has reached the loop bound and branches to exit.
- The loop loads and adds `a[i-1]` and `a[i-2]`; the lecture notes a quiz-code typo and a possible missing store separately from the intended branch answer.
6:53
Bit Shifts, Simulation, Synthesis, and Multiple Drivers
- Left-shifting one 16-bit half and right-shifting the other, then OR-ing them, swaps the upper and lower halves of a register and destroys the original value.
- SystemVerilog supports both simulation and synthesis, and can describe structural as well as behavioral hardware.
- Two continuous assignments that drive one signal can conflict; simulation represents the conflict as `X`, while a tri-state `Z` driver represents a disconnected output.
11:36
Four-State Logic and Signal Values Across Module Hierarchy
- A SystemVerilog `logic` value can be `0`, `1`, `X`, or `Z`; `X` flags unknown or conflicting values, while `Z` represents high impedance.
- Named port connections can rename signals across module boundaries: the `bottom` module instance receives `a=1` and produces `y=0` when its logic inverts the input.
- A signal can be driven indirectly through a module output, so checking only the top-level assignments may miss a multiple-driver conflict.
19:34
Structural HDL, Bit Manipulation, and the Lab 2-to-Lab 3 Path
- Structural HDL connects module instances through signals; behavioral HDL in the earlier material used `assign` statements and the ternary operator.
- Bit slicing selects ranges such as `a[2:0]`, concatenation orders the most-significant bits on the left, and replication can duplicate a bit into a wider signal.
- Lab 2 connects groups of four FPGA switches to seven-segment decoders; Lab 3 reuses the switches, displays, and decoders with a CPU inserted between them.
23:52
Lab 2 Files, FPGA Pins, and Simulation Wrappers
- The project skeleton includes `simtop.sv`, `top.sv`, and `hex_driver.sv`; the decoder implementation is completed in the provided driver file.
- The FPGA board has eight hex displays, each with seven segment signals, for 56 display-control wires; the board constraint file maps signal names to physical pins.
- `top` is intended for FPGA implementation, while `simtop` wraps it with testable inputs and observable outputs for simulation.
29:34
ModelSim Compilation, Waveforms, and Manual Input Forcing
- Compile SystemVerilog with `vlog` before simulation; the compiled modules appear in ModelSim's `work` library.
- Choose the simulated top-level module, add signals such as `A`, `B`, `C`, and `Y` to the waveform, and advance time with `run`.
- Uninitialized inputs begin as `Z`, which can propagate to `X` through Boolean logic; forcing `A=1`, `B=1`, and `C=0` demonstrates the NAND-and-inverter outputs.
40:00
Building a Repeatable Test Bench with an Initial Block
- A test bench has no ports and instantiates the design under test, connecting its inputs and outputs to local signals.
- An `initial` block runs once at simulation startup; use `begin` and `end` when it contains multiple statements, then assign input values and insert `#` delays.
- A test bench preserves stimulus across simulation restarts, avoiding repeated manual input forcing, but waveform inspection still requires checking outputs by hand.
47:27
SystemVerilog Always Blocks and Sensitivity Lists
- `assign` describes continuous combinational behavior, while `always` blocks support procedural constructs such as `if`, `case`, and loops.
- `always_comb` implies sensitivity to combinational inputs; `always_ff` marks clocked sequential logic and helps catch coding errors.
- A clocked process responds to clock edges, while combinational logic must reevaluate when its inputs change; a plain `always` block with no sensitivity list is useful for simulation but is not synthesizable.
53:45
Combinational Muxes, Output Ownership, and Accidental Latches
- A ternary `assign` and an `always_comb` block with `if/else` can both implement a 2-to-1 mux selecting between `foo` and `bar`.
- Every output in a combinational `always` block must receive a value on every control path; omitting an `else` can infer a latch that retains the prior value.
- Each `assign`, module output, or `always` block drives its signals, so assigning one signal from multiple independent sources can cause a driver conflict.
58:06
Default Assignments and Case Statements for Control Logic
- Assigning default values at the top of an `always_comb` block ensures every output has a value, then branches can override only the signals that differ.
- This default-first style is useful in a CPU control unit, where one instruction such as `ADD` can define defaults and `SUB` can override just the ALU operation.
- A `case` statement selects behavior by input value; underscores in numeric constants improve readability and are ignored by SystemVerilog.
1:04:44
How Incomplete Sensitivity or Assignments Infer Memory
- A clocked block such as `always @(posedge clock)` updates a register on the rising edge even when data input `B` is not in the sensitivity list.
- Combinational sensitivity with incomplete output assignments also implies storage: an output must retain its previous value on paths where no new assignment occurs.
- `always_comb` and complete defaults help reveal or prevent unintended storage in combinational logic.
1:06:44
Latch Versus Flip-Flop Timing and Why Latches Are Avoided
- A latch is level-sensitive: while its clock is high, `Q` follows `D`; when the clock goes low, it holds the last value.
- A flip-flop is edge-triggered and samples `D` at a rising or falling clock edge, like a camera capturing a single instant.
- Edge-triggered flip-flops make timing analysis more manageable; Bakos advises avoiding latches in on-chip designs because level-sensitive timing is difficult to constrain.
1:12:34
Self-Checking Test Benches and the Propagation-Delay Epsilon
- A basic self-checking test bench assigns inputs, waits briefly, and uses an `if` statement plus `$display` to report an unexpected output.
- RTL simulation does not model physical capacitance, resistance, or real signal propagation, but a small delay such as `#10` lets scheduled logic updates settle before checks.
- The delay-based approach is an improvement over visual inspection but is less structured than clock-coordinated stimulus and checking.
1:13:07
Clocked Test-Bench Checks and Test-Vector Files
- A clocked test bench can set inputs on the rising edge and check outputs on the falling edge, separating stimulus from verification.
- A test-vector file records inputs alongside expected outputs so the test bench can compare results automatically.
- The approach combines `initial` setup with an `always` clock process and provides a repeatable testing pattern for the FPGA labs.
1:15:04
Applying Test Benches to the FPGA Labs
- Lab work benefits from a self-checking test bench that exercises decoder inputs and verifies expected segment outputs.
- Simulation checks RTL behavior before FPGA deployment; if hardware behavior differs, Quartus tools and JTAG signal probing can help investigate.
Summary, takeaways, and chapters were generated by AI from the video's transcript and may contain errors. The video belongs to its creator, Jason D. Bakos.