 # Sequential signals may hide combinational ones ¶

Verilog is a hardware language with a syntax similar to C, but very different semantics: signals, circuits, and registers for storing the state.

## Registers and sequential logic ¶

```                 ┌─────┐
some circuit  >──┤D   Q├──>  some circuit
│     │     updated one clock edge later
┌─>     │
│ └─────┘
clock
```

They use the `<=` assignment operator to build-up sequential logic. Like software variables, they can hold values across multiple clock cycles. An assignment to a register (on `D`) gets read (on `Q`) on the next clock cycle.

```reg r;
always_ff @(posedge clk) begin
r <= 1;             └── This is the clock connected to all registers
end    └── This is the input signal D fed into the register

wire w = r;
└── This is the output signal Q read from the register
```

## Wires, signals, and combinational logic ¶

```some circuit  >───────────────>  some circuit
the_wire_name
```

Most verilog expressions gets converted to a circuit of gates implementing it. The `=` assignment used in various contexts permit to attach an end of a wire to a name, a label. The `always_comb` block can only have `=`, no `<=`, and implement combinational logic.

```input i;
wire [7:0] w;
always_comb begin
w = i ^ 8'b10101010;
end
```

## How combinational logic appear ¶

But what if complex expressions are assigned to a register instead of a wire? The signal coming into the register may be represented as an expression itself, and expressions are combinational logic. The flip-flop-only `always_ff` contains, in fact, a mix of combinational and sequential logic.

The restriction in `always_ff` is that adding extra combinational logic is forbidden (no `=` operator) but combinational logic feeding registers can still occur. It helps with preventing `<=` being typoed into `=`.

```input i;
reg [7:0] r;
always_ff @(posedge clk) begin
r <= i ^ 8'b10101010;
end
```

This is not a problem per-se, just a remark.

## The LowRISC approach ¶

The above permits us to explain the approach LowRISC is taking. The team described it in their style guide for SystemVerilog:

It is done by coupling a `always_ff` that applies the changes to registers, with `always_comb` that build-up the next values. Each register is having:

• a `_d` wire that is fed into the register, driving the next value of the register;
• a `_q` register, representing the output value of the register, which is delayed by one clock.

On each clock, this happens alone in a block: `something_q <= something_d`; and the rest is purely combinational.

In other words, the sequential operation have been isolated, by giving the input signal a name (`something_d` here).

```wire something_d;
reg [7:0] something_q;
always_ff @(posedge clk) begin
// apply the changes to the registers
something_q <= something_d;
end

always_comb begin
// by default, the value stays the same as the register previous value
// this was happening under the hood in the previous examples, it is now
// explicit
something_d = someting_q;

// for giving something_q another value, something_d can be changed with
// in the combinational logic
if (i > 3) begin
something_d = something_d + 1;
end
end
```

## Extra convention ¶

In addition to LowRISC guideline, I also use this convention: When declaring signals with `logic`, the `_d` wire comes first, followed by `_q` and `_q2` etc. That way, there is one line per signal, including its past state. This help with reading code faster:

```logic ack_d, ack_q, ack_q2;
logic state_d, state_q;
logic counter_q;
```

## In practice? ¶

Inconvenients:

• More verbose outside the combinational block;
• Extra signals to declare (the `_d` ones):

• Everything is explicit around the registers;
• In expressions using these signals, change `_q` into `_d` to save one clock cycle;
• Consistent naming using the `Q`/`D` signal naming of registers.

It is also frequent to have a reset signal that puts all registers to a default value. The LowRISC approach makes it convenient to integrate it within the `always_ff` block, introducing a little bit of combinational logic, without much effect.

```always_ff @(posedge clk) begin
if (rst) begin
something0_q <= 0;
something1_q <= 0;
something2_q <= 0;
something3_q <= 0;
end else begin
something0_q <= something0_d;
something1_q <= something1_d;
something2_q <= something2_d;
something3_q <= something3_d;
end
end
```

In a real world example, I would have been using `logic` instead of `wire` and `reg`, the `_q` and `_d` helping with making the distinction. I would also likely use `rst_ni` instead of `rst` and `clk_i` instead of `clk`.

Also sometimes the whole design is so trivial that a separate `always_comb` would be an overkill.

https://lowrisc.org/

https://github.com/lowRISC/style-guides/blob/master/VerilogCodingStyle.md