1 / 37 · Concept
RTL: describing concurrent circuits
Separate software execution order from parallel hardware structure and specify state, next state and observation times.
Lessons are free to read. Enroll to save your learning progress.
A circuit continues to operate
RTL describes how values move between registers through combinational logic. A module is a hardware boundary; instantiating two modules creates two interacting structures. It does not mean “call the first function, then the second.” The circuit remains active as its inputs change.
Digital Logic Circuits introduced gates, storage and state machines. This course turns those ideas into explicit SystemVerilog interfaces and repeatable verification. You should be able to explain every signal’s width, driver, valid time and reset behavior before writing the implementation.
Separate the current state from the next state
This complete module accumulates unsigned four-bit samples into an eight-bit register. Reset is active high and synchronous. Reset has priority over enable. An enabled edge adds the sample; another edge holds the sum. Arithmetic wraps modulo 256.
module accumulator (
input logic clk, rst, enable,
input logic [3:0] sample,
output logic [7:0] sum
);
logic [7:0] next_sum;
assign next_sum = sum + {4'b0000, sample};
always_ff @(posedge clk) begin
if (rst) sum <= 8'b0;
else if (enable) sum <= next_sum;
end
endmodulenext_sum is a combinational result. It can change when sum or sample changes, even without a clock edge. sum stores state and changes at a rising edge. Declaring both as logic does not give them the same hardware role.
The missing final else in this clocked block means “hold the register.” A missing assignment in a combinational block can require a latch instead. Always ask which type of block you are reading before interpreting an omitted assignment.
Calculate an edge table before simulation
Each row uses the state and inputs immediately before the edge. Observe the stored result after the edge’s nonblocking updates.
| Edge | rst | enable | sample | sum before | sum after |
|---|---|---|---|---|---|
| E0 | 1 | 1 | 9 | Unknown | 0 |
| E1 | 0 | 1 | 3 | 0 | 3 |
| E2 | 0 | 0 | 7 | 3 | 3 |
| E3 | 0 | 1 | 5 | 3 | 8 |
| E4 | 1 | 1 | 15 | 8 | 0 |
At E4, reset wins. No addition occurs. If the old sum is 250 and the accepted sample is 10, the new eight-bit sum is 4. Preserving a ninth bit would be a different interface and arithmetic contract.
Assignment order is local, concurrency is structural
Blocking = assignments inside a combinational procedure execute in procedural order. Separate procedures and continuous assignments are scheduled as concurrent processes. Nonblocking <= assignments in a clocked procedure calculate right-hand sides using the values available when the process executes, then schedule updates. Source order is not a substitute for a latency specification.
Do not put #10 into this accumulator to mean “wait one clock.” Delays and clock generators belong to the general-purpose simulation testbench used later. A synthesizable state transition expresses a clock edge and state, not a software sleep.
Practice · Change one requirement
Change the behavior from wrapping to saturating at 255. First compute a nine-bit addition from explicitly extended operands. If bit 8 is set, store 255; otherwise store bits 7:0. Keep reset and enable priority unchanged. Test 0+0, 250+5, 250+6, a disabled edge and simultaneous reset/enable.
Expected results: 0, 255, 255, held state and 0 respectively. The saturation test must include 250+6; checking only 250+5 cannot expose lost carry.
Save the source, edge table and expected results together. A learning-completion mark records that you studied the lesson; it is separate from a simulator run.