[Hardware Design III] Configurable Designs

Fábio Magalhães
May 12 · 6 min read

Hardware components are developed as static modules, that for a given set of inputs generate a set of outputs within a bounded latency. The component is developed for a specific task and changes to the use case involve code refactor. Targeting an easier solution for module configuration and parameterization, specific constructs were built into the Hardware Description Languages(HDL) that allow the Hardware Designer to implement and instantiate several configurations of an HDL module without requiring to rewrite code.

Parameters

Parameters are an HDL construct used for the development of parameterized modules and are mostly used in the declaration of the module’s signals, to set the intended number of bits, or as constant values within the module’s logic.

The adder module’s code exemplifies how parameters allow specification of the implementation’s bitwidth through the Parameter construct. Upon instantiation of the adder module, the user can set the bitwidth parameter to the desired value.

module adder
(parameter bitwidth = 8)
(
input [bitwidth - 1 : 0] opA,
input [bitwidth - 1 : 0] opB,
output [bitwidth - 1 : 0] res
);

For Loop

The For Loop is an HDL construct applicable for both synthesizable and non-synthesizable code and is used to expand replicated logic in the design. This construct is a simple way of shrinking the amount of code written and enables the customization of the Design, using a parameter the user can define the number of logic operations implemented in parallel within the Foor Loop.

The following HDL snippet shows one implementation using the For Loop construct, where an XOR operation is applied between the opA and the matching inverse-order bit of opB. The For loop construct will generate the XOR logic, with the 8 operations implemented in parallel.

for(i = 0; i < 8; i = i + 1) begin 
assign opA[i] = opA[i] ^ opB[bitwidth-1-i];
end

Compiler Directives

The Compiler Directives are instructions to the Verilog Compiler and enable the configuration of the HDL Design’s Architecture and Port Interface. The Hardware Designer can specify certain blocks of code to be implemented only when the expected define is present in the code.

The Compiler Directives of the adder module support implementation with and without the Carry signals, depending on the inclusion of `define CARRY_CONFIG.

module adder
(parameter bitwidth = 8)
(
input [bitwidth - 1 : 0] opA,
input [bitwidth - 1 : 0] opB,
`ifdef CARRY_CONFIG
input carryIn,
output carryOut,
`endif
output [bitwidth - 1 : 0] res
);

Generate Construct

The Generate statement is a powerful construct for the development of configurable HDL designs. The Generate is designed for two use cases: Multiple Instantiation and Conditional Configuration.

Multiple Instantiation implements N instances of the target module, which can be connected or parallel. Conditional Configuration implements different configurations of logic, depending on the value of an associated parameter.

The Generate construct requires, in most cases, a small adaptation of the HDL code to support the statement, such as redirecting input data into multi-dimensional signals or a concatenation signal.

Multiple Connected Instantiations

The Generate Construct enables the connection of N instances of an HDL module, resulting in a more complex Design. One good example to demonstrate the applicability of this concept is the Adder, which connected with more instances of the module implements the Addition operation for a wider bitwidth, as shown in figure 1.

figure 2 — N Connected Instances Adder Example.

The Generate is combined with the Parameter and For Loop constructs, which are used to implement the number of instances connected to the Adder 0 module by replicating the logic, as represented in the cutline section of the diagram.

The following Generate snippet translates the Block Diagram from figure 1 into HDL code, where the For Loop index is used to connect the Carry signals from the instances, as well as selecting the data sections processed by each.

generate
for(i = 1; i < N; i=i+1)begin
adder #(.bitwidth(8))
adder_ip(
.opA(iA[i*8 + 8 - 1 : i*8]),
.opB(iB[i*8 + 8 - 1 : i*8]),
.carryIn(ocarry[i-1]),
.carryOut(icarry[i]),
.res(oRes[i*8 + 8 - 1 : i*8])
);
end
endgenerate

The Foor Loop index is set to 1 at the start since Adder 0 is always implemented while the cutline section is optional, depending on the bitwidth intended by the user. For the instance i the carryIn is connected to the carryOut of instance i-1, i.e., the Carry-In signal of the instance is wired to the instance Carry-Out that is processing the predecessor block of data, as exemplified in the Block Diagram in figure 2.

Multiple Parallel Instantiation

The Generate construct also enables Parallel Instantiation, which implements N instances of an HDL module in parallel, as represented in figure 2.

figure 2 — N Parallel Instances Adder Example.

The cutline section of the Block Diagram represents the N components that can be implemented parallel to the Adder 0 module, increasing the number of elements processed by the component and, consequently, the throughput.

The next snippet transforms the Block Diagram in figure 2 into HDL code, where the For Loop index is used to select which data is allocated to each instance.

generate
for(i = 0; i < N; i=i+1)begin

adder #(.bitwidth(8))
adder_ip(
.opA(idata_stream[i*8 + 8 - 1 : i*8]),
.opB(idata_stream[i*8 + 8 - 1 : i*8]),
.res(odata_stream[i*8 + 8 - 1 : i*8])
);
end
endgenerate

Conditional Configuration

The Conditional Configuration is a very powerful concept, which allows the Hardware Designer to develop several configurations of an HDL Module, selectable through the value of a dedicated parameter.

The Conditional Configuration concept enables the Block Diagram of figure 3, where the arith_unit module supports 4 different configurations. The user instantiates the module with the chosen configuration, by setting the ARITH_BLK_CFG parameter to the intended value.

figure 3 — Conditional Configuration example.

In the Conditional Configuration implementation, the Generate construct is combined with Compiler Directives, more precisely the Ifdef directive, to specify the logic implemented for the different values of the ARITH_CFG.

module arith_unit
(parameter bitwidth = 8,
parameter ARITH_CFG = 0
)
(
input [bitwidth - 1 : 0] opA,
input [bitwidth - 1 : 0] opB,
`ifdef ARITH_MUL
output [2*bitwidth - 1 : 0] res
`else
output [bitwidth - 1 : 0] res
`endif
);

For cases where there is a large number of configurations, the Case construct can be combined with the Generate to produce the same behavior of the Ifdef directive, as represented in the following arith_unit implementation.

module arith_unit
(parameter bitwidth = 8,
parameter ARITH_CFG = 0
)
(
input [bitwidth - 1 : 0] opA,
input [bitwidth - 1 : 0] opB,
`ifdef ARITH_MUL
output [2*bitwidth - 1 : 0] res
`else
output [bitwidth - 1 : 0] res
`endif
);

The Generate, For Loop and Parameters are powerful constructs to develop configurable HDL modules, facilitating the process and avoiding unnecessary code modifications for every new instance that requires a different configuration. The Hardware Designer is presented with a tradeoff between the required code insertion, to adapt the Design’s logic for the Generate and For Loop constructs, and the reconfigurability added to the Design.

Geek Culture

Proud to geek out. Follow to join our +500K monthly readers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store