Structvhdl
Structvhdl
Jiri Gaisler
begin
if Reset_Out_N = '0'then
CBLatch_F_1 <= "0000";
elsif MDLE = '1'then
CBLatch_F_1 <= CB_In(3 downto 0);
end if;
end process;
q
Comb
d q = f(d,qr)
DFF
qr
Clk
2: the abstracted view in VHDL
The two-process scheme
A VHDL entity is made to contain only two processes: one
combinational process
The combinational process is sensitive to all input ports and
Q Out-port
In-ports Comb. Pro.
d q = f1(d,r)
ri = f2(d,r) ri Seq.
Process
r
Clk
Two-process scheme: data types
The local signals r and rin are of composite type (record) and
end architecture;
Hierarchical design
use work.interface.all;
Grouping of signals makes
end architecture;
Memory
Benefits
Add port in entity port Add element in the interface
declaration record
Add port in sensitivity list of
declaration
Add signal declaration in parent
module(s)
Add port map in component
Add signal declaration (2 sig.) Add definition in register record
Add registered signal in process
process
Tracing signals during debugging
Figure out which signals are Add interface records, r and rin
registered, which are their inputs,
Signals are grouped according to
and how they are functionally
related function and easy to understand
Addition/deletion of record
Add signals to trace file
elements automatically
Repeat every time a port or propagated to trace window
register is added/deleted
Stepping through code during debugging
Connected processes do not Add a breakpoint in the begining
execute sequentially due to delta of the combinational process
signal delay
Single-step through code to
A breakpoint in every connected execute complete algorithm
process needed
Next signal value (ri) directly
New signal value in concurrent visible in variable v
variable v : reg_type;
global package (e.g. EDAC) begin
end process;
1 entity, 2 processes
44 sub-programs
13 signal assignments
Reverse-engineered from
variable v : reg_type;
directly synthesisable by modern begin
tools
proc_irqctl(sysif, r, v);
All variables have to be assigned
rin <= v;
Avoid recursion, division, access
Ad-hoc method (15 designers) Two-process method (mostly)
25,000 lines of code 15,000 lines of code
45 entities, 800 processes 37 entities, 75 processes
2000 signals 300 signals
3000 signal assigments 800 signal assigments
30 Kgates, 10 man-years, 100 Kgates, 2 man-years, no
Benefits Problems
Easier to understand the Keep the code synthesisable
underlying algorithm
Synthesis tool might choose
Easier to modify/maintain wrong gate-level structure
algorithm for less skilled
Use built-in module
engineers
generators (synthesis)
Using records
f1 : std_logic_vector(0 to 7);
f2 : std_logic_vector(0 to 7);
Nested records further improves
f3 : std_logic_vector(0 to 7);
readability end record;
x1 : std_logic_vector(0 to 3);
x2 : std_logic_vector(0 to 3);
Element name might be difficult
x3 : std_logic_vector(0 to 3);
to find in synthesised netlist end record;
variable v : regtype;
v.reg1.f3 := “0011001100”;
Using ieee.std_logic_arith.all;
<>) of st_logic;
available type signed is array (natural range
<>) of st_logic;
Declares to additional types:
v1(0) := u1(conv_integer(u2));
available in all simulators and
synthesis tools
IEEE alternative: numeric_std
Use of loops
end if;
priority encoding, sub-bus end loop;
extraction, bus turning
-- reverse bus
for in 0 to 7 loop
v1(i) := v2(7-i);
end loop;
Multiplexing using integer conversion
return std_logic is
variable res : std_logic_vector(v'length-1
downto 0);
variable i : integer;
begin
res := v; -- needed to get correct index
i := conv_integer(unsigned(s));
return(res(i));
end;
std_logic_vector is
variable res :
std_logic_vector((2**v'length)-1 downto 0);
variable i : natural;
begin
res := (others => '0');
i := conv_integer(unsigned(v));
res(i) := '1';
return(res);
end;
State machines
architecture rtl of mymodule is
Simple case-statement type state_type is (first, second, last);
end record;
signal r, rin : reg_type;
Both combinational and begin
comb : process(...., r)
registered output possible begin
case r.state is
when first =>
if cond0 then v.state := second; end if;
when second =>
if cond1 then v.state := first;
elsif cond2 then v.state := last; end if;
when others =>
v.drive := '1'; v.state := first;
end case;
if reset = '1' then v.state := first; end if;
modout.cdrive <= v.drive; -- combinational
modout.rdrive <= r.drive; -- registered
end process;
.
Conclusions
Readability