With SpeakHDL, an architectural framework consists of :
Although any one of the three elements has the possibility of incrementally reducing development time, it is their use in tandem which provides the most design productivity. A flat architecture serves as a template for a design, while the API encapsulates the operations which can be performed within the architecture, and scripting provides a way to easily setup the and validate architecture.
SpeakHDL utilizes a flat design architecture which differs from the traditional hierarchical architecture that is typically found in FPGA design. Flattening the architecture offers an immediate opportunity for FPGA design simplification. This is due to the fact that all modules appearing on a flat architectural level are inherently decoupled from any sub-component dependencies. A flat design architecture also makes the FPGA design problem much more tractable, both from a graphical stand point and from a coding stand point. SpeakHDL takes advantage of this by introducing a centralized framework module to manage the hardware resources for all application modules that appear on the same architectural level. Introduction of a framework module is the key step in making procedural programming useful for FPGA design.
An application module is a VHDL entity that adheres to the common port interface required for use in the design pattern. The port interface contains (7) signals, two of which are the
system clock and reset signal
. In addition, each application module is assigned a
VHDL generic constant
module index for identification purposes and is connected to the framework module through its
next_state_rec
and
state_reg_rec
signals which make up the façade object in the
façade design pattern
. When an application module makes a procedure call, it is really a request to the framework to configure a synchronous hardware component (such as counter or fifo) on it's behalf. Application modules can be logically connected to one another by way of the framework module and data can be passed back and forth using a framework shared register or framework fifo.
What makes an application module different than a normal VHDL entity is that an application module has the following restrictions:
An application module:
The framework module is a VHDL entity that acts as a centralized distributer of synchronous hardware resources (such as a fifos, counter, registers). When a procedure call is made, an application module configures a hardware resource combinatorically through its
next_state_rec
signal, and the framework module returns registered logic by way of the
state_reg_rec
signal. During synthesis, it is the framework module that actually implements the logic that is requested by the application modules when a procedure call is made.
In addition, the framework module handles the clock and reset signals for the requested resource. This is very productive for FPGA design. By consolidating the clock and reset signal into the framework module, application modules are not required to explicitly manipulate the clock and reset for hardware resources that are configured by API call.
The purpose of the framework module is to:
In SpeakHDL, the term
hardware resources
or
framework resources
relate to either:
Inside the framework module, each hardware component is
not
managed individually. Instead, the framework bundles hardware components into a groups of components called a framework resource. A
single
framework resource contains a state machine, a receive fifo buffer, a dual counter used for timing, a shared register, a left and right shift register, an array of general purpose counters, an array of edge detectors, and an array of event signals.
The framework module contains an
array
of these bundled resources.
Framework resources can be placed either on the same clock domain or on
multiple clock domains
. When not necessary to differentiate, the terms
resource_index
and
resource domain
can be used interchangeably and are used to identify a grouping of hardware components that that reside on the
same
clock domain with the
same
resource array index. This is subtly different than describing components on the same
clock domain
as there can be multiple framework resource indexes placed on the same clock domain.
SpeakHDL provides the suitably named
RESOURCE_SELECT
procedure call in order for the developer to specify which resource index a hardware component should be selected from. Any procedure calls that appear after the RESOURCE_SELECT procedure call with the specified
resource index
is taken from the same resource domain. The term
resource index
is typically used in relation to how an API call is made. For example, consider the following API calls:
SpeakHDL requires that an FPGA design have a system clock signal and a global reset signal and also have an FPGA pin location assigned to each of them. When the reset signal is asserted, the framework module handles the responsibilities of resetting any hardware configured by procedure calls (counters, fifos, state machines, ect). Thus the developer is only responsible for resetting logic that gets inferred within an application module. This typically results in the clock and reset signals just being routed to components and IP blocks. After the reset is asserted, it is ensured that on the next rising edge of the system clock the following will occur:
Although it is not displayed on most diagrams, the system clock and reset signal are fanned out from the FPGA input pins to the framework module and to all application modules. However, the clock and reset signal need not be used within and application module to achieve the functionality provided by API calls. Instead, a developer may choose to make use of the implicit reset value of framework hardware components.
An example of taking advantage of an implicit reset value can be seen with the LED blink example . Inside the code, there is no reference to what the state of the LEDs should be upon reset. However because it is known that all framework counter values will be set to zero on system reset, the comparison logic has it such that the LEDs are off when the reset is asserted.
On the other hand, a user may choose to be more explicit as to what value output signals should be driven to upon system reset. A developer may choose to utilize the value of the reset signal directly or may use the initial value of the state register when setting combinatorial output signals. When there is a state machine already in use, it may make sense to drive output signals to a known state when state_reg = 0 .
In order to synthesize the design, SpeakHDL requires a
clk_pin
location to be mapped to a clock oscillator on the development board and
reset_pin
location which can be mapped to any input pin location (button or switch, ect). Before any clock and reset location have been specified, SpeakHDL sets the default pin locations to be '<>' and prints these locations as VHDL comments next to the
port interface
of each application module.
When either the clock or reset pin locations are not specified, SpeakHDL will generate at least one
error
when the 'ok' command is given.
Details for the errors and warnings can be viewed in the
ok.log
file. After pin location information for the clock and reset pin are given, SpeakHDL will show an
ok
status.
One productivity enhancing feature used by SpeakHDL is the enforcement for a uniform VHDL code structure. Every application module follows the same text file structure from top to bottom. Each of the following VHDL code construct are displayed in order.
SpeakHDL
does not
allow the
"if-then-else"
VHDL construct to appear inside of an application module. The constraint is by design and has a rather profound impact on how the design pattern is formulated. Due to the constraint, conditional logic operations must either be made using an "
when-else
" statement outside of the process construct or a
CONDITIONAL_TRANSITION
procedure call.
This requirement implicitly forces a developer to:
In addition, the lack of an
"if-then-else"
statement inside of a process implicitly prohibits the developer from inferring an RTL register due to the process. As a consequence, application modules typically only infer combinatorial logic if they do not instantiate any components.
SpeakHDL dramatically reduces the amount of signal declarations that are necessary when compared to traditional RTL style coding. One may look at the
next_state_rec
and
state_reg_rec
signals as a large number of pre-declared signals that a developer can immediately take advantage of. In addition, SpeakHDL
automatically creates signal declarations
for supported data types when signal assignments are made. In order to lower design complexity, SpeakHDL only support signal assignments for the most useful VHDL data types which are synthesizable. These data types include:
State machines are defined to have an
integer
state type and all
std_logic_vector
signal assignments assumed to have a
downto
range.
VHDL constant
declarations (which are not a state machine state name) and VHDL
aliases for framework signals
are viewed as a form of configuration data and are captured in the local section of the config file.
With SpeakHDL, there is no real concept of a traditional HDL testbench. When using the design pattern, it is assumed that the API library has been rigorously tested and is operational. Thus, it is possible to use the API to generate stimulus waveforms for validation purposes. Due to the loose coupling of application modules, any application module can be used to generate test stimulus. One or two application module can be validated while the others are
set disabled
. Once a sufficient level of confidence is obtained in the tested portion, other application modules can be gradually added to the design.
One rationale for using the API to generate test stimulus, is that application modules must use the API for communication during normal operation anyway. Communication is always performed through the use of the SHARED_REGISTER or WRITE_FIFO_DATA procedure calls. In addition, the API can be used to simulate drivers for internal signals and output signals. However, the API cannot be used to simulate driving of input signals which enter from the FPGA pins. To simulate input signals, a traditional a traditional testbench must be created or a work-around must be performed.
One possible work-around to simulate signals which originate from an external source would be to temporary replace the application module's input signals with local signals which are driven internally. After the replacement is made, the API once again can be utilized to exercise the logic. Local signals can be easily driven through the use of a state machine by creating transitions using timing functions .
With SpeakHDL there is at least one clock domain called the
sys_clk
domain with the default frequency of 100MHz if no other frequency is specified within the
configuration file
. Thus, there will be at least one framework module that handles the system clock and global reset signal. SpeakHDL handles multiple clock domains by through the use of multiple framework modules. Each framework module is responsible for handling the synchronous hardware components on its respective clock domain. To configure hardware that operates on separate clock domains, all that is needed is to make multiple calls to the
RESOURCE_SELECT
procedure on separate
resource indexes
and to give a clock frequency other than
sys_clk
as the first argument.