Assignment in Combinatorial Circuits

Continuous Assignment

For simple combinatorial logic, we can use continuous assignment with the assign keyword:

wire x;
assign x = a + b;

Assignment Blocks

For more complex logic, we can use the more flexible always keyword, using blocking assignment (=):

reg x;
always @ (*)
	case (select)
		0: x = a;
		1: x = b;
		2: x = c;
	endcase

Variables assigned in an always statement must be defined as reg rather than wire, although this does not mean that they will be synthesised as a register in hardware. A register should not be able to exist in a combinatorial circuit.

Sensitivity List

The always statement takes a sensitivity list in brackets. This defines the dependencies that will trigger a re-evaluation of the block when changed. This can be substituted with an asterisk (*) to indicate that the block should be re-evaluated when any of its dependencies changes.

Sometimes, such as when using the clock signal, it may not be desirable to have any change in a signal in the sensitivity list result in the block being triggered. For this, a signal in the sensitivity list can be preceded by one of the following two keywords:

  • posedge x - Only the rising edge (x changes from 0 to 1) will trigger the block.
  • negedge x - Only the falling edge (x changes from 1 to 0) will trigger the block.

Assignment in Sequential Circuits

Combinatorial logic can exist within a sequential circuit using assign and always statements as defined above. Sequential logic can be created using an always statement triggered by a clock signal.

Similarly to with combinatorial circuits, all variables assigned inside an always statement must be defined as reg. always blocks in sequential circuits should be triggered on the rising or falling edge (posedge or negedge respectively) of a clock signal. Assignment should be done using the non-blocking <= operator. As such, assignments will be executed concurrently and should not depend on each other.

reg x;
always @ (posedge clk)
	begin
	if (enabled)
		x <= ~x;
	end

Synchronous and Asynchronous Sensitivities

This is most commonly relevant when dealing with reset signals, where a synchronous reset signal will trigger a reset only when the clock goes high, whereas an asynchronous reset will trigger as soon as it goes high, regardless of the clock. This is specified by the inclusion (asynchronous) or exclusion (synchronous) of the given signal from the sensitivity list, and is an important design decision.