Clocked Shorthand
Proposal Details
- Who Updates: DanielKho, JimLewis, ...
- Date Proposed: 4 Jan 2012
- Date Last Updated: 4 Jan 2011
- Priority:
- Complexity:
- Focus:
See also
ISAC IR-2034 and
ISAC IR-2035.
Related Issues
*
MultiCyclePath*.
Current Situation
A couple of discussion threads on the reflector expressed a desire for:
- Shorthand for clocked processes - to reduce amount of boilerplate typing
- Shorthand for pipelining - this was also referred to as adding a "z-transform" function. This has two benefits - reducing boilerplate code, but more importantly explicitly signalling the tools that a pipeline chain is what is required, and removing a clutter of intermediate signals which are otherwise explicit in the source.
((Also falling into this "heading" were some suggestions on a library of standard functions (like and, or, mux2, ....). I will discuss these in another place (link to be added!)))
Requirement Summary
To reduce the amount of typing involved in creating clocked processes
To reduce intermediate signal clutter
To more explicity state intention to tools
Demonstrate (via examples) of support for numerous flip-flop coding styles: simple (no reset), reset (asynchronous, synchronous, power-on), load enable, mixing registers that have reset with those that do not, clock gates
Code Examples & Use Models
A number of possible syntaxes were discussed.
Non-Syntax Option:
Use a procedure call per
ExtendedHwFunctions.
Reg(Clk, D, Q) ;
RegPipe (Clk, D, Q, 5) ; -- adds a 5 deep pipelining / shift register.
Current Syntax Option:
Q <= D when rising_edge(Clk) ;
type
RegBankType is array (gDEPTH downto 0) of std_logic_vector(gWIDTH downto 0) ;
signal aQ :
RegBankType ;
aQ <= aQ(gDEPTH -1 downto 0) & D when rising_edge(Clk) ;
Q <= aQ(gDEPTH) ;
Tap1 <= aQ(TAP1_INDEX) ;
With VHDL-2008 and unconstrained arrays of arrays could use a standard type for arrays of std_logic_vector
Proposed Syntax Option 6/16/2016:
Q <= D @ 2 when rising_edge(Clk) ;
Q <= D[2] when rising_edge(Clk) ;
...
How does reset work and clear out the pipeline?
Offers little over the vhdl-2008 syntax, especially for complex cases.
Could work this in with channels proposal
AsynchronousChannels
Syntax Option 1:
Text originally on Collected Requirements Page:
- Create default attributes to define registers
- Syntax A <= B @ 2; -- B becomes A after 2 clock cycles
- Predifined attribues like clock, reset, reset_value, enable, rising_edge would be needed.
- Put on a signal, a group, or an entity.
- Allow synthesis if "@ 2" is used, ignore synthesis (sim only) if "after 2 ns" or "@ 2 ns" is used.
q <= d @ 2;
or
q <= d after 2;
with the '2' implying 2 cycles. Attributes could then be assigned at the entity or signal level to define clock signal, reset value, enable, etc;
attribute default_clock : STD_ULOGIC;
attribute default_reset : STD_ULOGIC;
attribute default_enable : STD_ULOGIC;
attribute default_reset_value : STD_ULOGIC;
attribute default_clock_edge : STD_ULOGIC;
attribute default_clock of ent1 : entity is clk_sig;
which could lead to a very compact definition.
Use Cases
q <= d @ 2;
Asynchronous resets:
q <= x"0" when not nReset else d @ 2;
Synchronous resets:
q <= x"0" when not nReset and rising_edge(clk) else d @ 2;
Mathematical example that uses asynchronous reset:
q <= to_signed(0, dataWidth) when not enable else to_signed((d*123_456 - 78_901) / 2**d, dataWidth) @ 2;
Allow '@' notation within processes, so as to tell the synthesis tool to implicitly add pipeline registers:
p0: process(clk,enable) is begin
if enable='0' then q <= to_signed(0, dataWidth);
elsif rising_edge(clk) then
q <= to_signed((d*123_456 - 78_901) / 2**d, dataWidth) @ 2;
--more statements...
end if;
end process p0;
For dual-edge-triggered processes, the pipelined signal should appear considering both edges of the clock:
p1: process(clk,enable) is begin
if enable='0' then q <= to_signed(0, dataWidth);
elsif rising_edge(clk) or falling_edge(clk) then
q <= to_signed((d*123_456 - 78_901) / 2**d, dataWidth) @ 2; --here, "@ 2" means after 2 edge detections, i.e. after both rising and falling edges.
--more statements...
end if;
end process p1;
Arguments FOR
The 1st option allows for the implicit creation of the pipeline signals to reduce clutter, and for simple pipelines without reset logic could provide a compact representation.
Simplifies descriptions which are heavily mathematical- or DSP-based. Mathematical / DSP descriptions usually would require some level of pipelining, and the 1st option retains the original equations in the description. Without this, the description will be less understandable (the original equations will be "lost" or obscured), and it becomes more structural instead of behavioral.
If the equations involved are fairly complex, option 1 will reduce the amount of typing significantly, as it reduces the many intermediate signals which would otherwise have to be declared. Also, this reduces the many structural blocks that need to be described. Imagine having to instantiate a power-of-x and a divider and a few other mathematical blocks separately, then connecting all of them structurally together.
This introduces the ability to clock functions, as it signals the tool to automatically add pipeline registers even if the behaviour has been described using a set of functions.
Arguments AGAINST
This sounds scary and error-prone to me. With this approach I have to look all over the declarative regions inside and outside the entity (if the attribute is specified where the entity is instantiated) to find out what my clock is!
A decent IDE/editor removes most of the pain of boilerplate typing anyway.
Is the implicit creation of signals a bit "non-VHDL"?
Syntax Option 2:
Some more explicit variations on this theme include extending the definition of "time" to include events (and the * operator to count them, a bit like doing
2*1 ns
):
q <= d after 2 * (rising_edge(clk) and enable = '1');
Asynchronous resets could be achieved thus:
q <= "0000" when nReset = '0' else d after 2 * (rising_edge(clk) and enable = '1');
Synchronous resets would require something like:
q <= "0000" after (rising_edge(clk) and nReset = '0')
else d after 2 * (rising_edge(clk) and enable = '1');
Mathematical example that uses asynchronous reset: --
DanielKho - 2012-04-26
q <= to_signed(0, dataWidth) when not enable else to_signed((d*123_456 - 78_901) / 2**d, dataWidth) after 2 * rising_edge(clk);
A variation on this using processes (processes are often needed for multiple sequential statements): --
DanielKho - 2012-04-26
p0: process(clk,enable) is begin
if enable='0' then q <= to_signed(0, dataWidth);
elsif rising_edge(clk) then
q <= to_signed((d*123_456 - 78_901) / 2**d, dataWidth) after 2;
--more statements...
end if;
end process p0;
For dual-edge-triggered processes, the pipelined signal should appear considering both edges of the clock: --
DanielKho - 2012-03-11
p1: process(clk,enable) is begin
if enable='0' then q <= to_signed(0, dataWidth);
elsif rising_edge(clk) or falling_edge(clk) then
q <= to_signed((d*123_456 - 78_901) / 2**d, dataWidth) after 2; --here, "after 2" means after 2 edge detections, i.e. after both rising and falling edges.
--more statements...
end if;
end process p1;
Arguments FOR
Arguments AGAINST
Syntax Option 3:
label: process [rising|falling] clock(Clk) is
-- declaration region for constants, variables, aliases, etc.
[asynchronous|synchronous] reset(Rst)
-- reset logic
begin
-- non-reset logic
end process;
Arguments FOR
Arguments AGAINST
A comment was made that
This change doesn't give a huge benefit, but it ought to be easy to
specify and use.
Syntax Option 4:
Another possibility would be to provide an extra attribute on signals:
if clk'rising then
again, the benefit is marginal.
A variation on this theme was to allow functions in sensitivity lists to provide something like Verilog's sensitivity lists to define the clock edge (which reduces the need for the rising_edge() function within the process):
process (rising_edge(clk), falling_edge(reset_n))
begin
if reset_n = '0' then q <= '0'
else q <= d;
end if;
end process;
Arguments FOR
Arguments AGAINST
Use Cases
Syntax Option 5:
Use PSL:
q <= d after Tpd, e after T + Tpd, f after T + Tperiod_clk + Tpd;
General Arguments FOR (not specific to a Syntax Option)
General Arguments AGAINST (not specific to a Syntax Option)
Most of the syntaxes are not much (if any) shorter than what everyone uses daily at the moment.
General Comments
--
ErnstChristen - 2015-01-27
There are 2 proposals related to clock management.
It seems worthwhile to formulate generic requirements for handling clocks (semantics, usage, restrictions, etc.) before looking at individual aspects in isolation.
Supporters
Add your signature here to indicate your support for the proposal
--
DanielKho - 2015-01-01