entity Z_Adder is port ( Data_A : in integer_32; Data_B : in integer_32; Data_P : in integer_32; Z : out integer; Data_out : out integer_32; sign_Z, s : out bit; z1, z2 : in bit_vector (0 to 1); Z_op, zang : in bit_vector (0 to 1); f, Az, en : in bit; ph_1, ph_2 : in bit ); -- integer_32 is declared elsewhere to be a bit_vector ( 0 to 31). -- Note that letting Z simply be type integer suggests that the -- synthesis tool should produce a bit_vector capable of -- displaying the full range of integers, i.e. 32 bits. This is, -- in fact, just what was wanted. end Z_Adder; architecture Concurrent of Z_Adder is signal A_in, B_in : integer; signal Z1_in, Z2_in : integer; signal Zsum, Zang_out : integer; signal GND, open_src : integer := 0; signal Zc, Zc_in : bit; -- again, we would synthesize 32 bit buses for everything -- declared "integer." begin -- transmission gates from Data Buses A_in <= Data_A when ph_1 = '1' else A_in; B_in <= Data_B when ph_1 = '1' else B_in; -- Leaving out the else clauses here would be more efficient from -- a simulation point of view, but it makes explicit what the -- synthesis tool has to generate i.e., a memoried element. In -- some tools this would lead to a redundant feedback from Q -- back to D. -- z2, z1, and Z_op are control signals from -- IKS controller selecting one of 9 functions -- to be implemented in the Z_adder. with z1 select Z1_in <= GND when "00", Data_P when "01", A_in when "10", open_src when "11"; with z2 select Z2_in <= GND when "00", B_in when "01", Zang_out when "10", open_src when "11"; with Z_op(0) select Zc_in <= Z_op(1) when '0', Az when '1'; -- All three WITH statements produce the multiplexors we want. -- Use of block to show design partition. -- These are the ph_2 enabled latches shown in the figure above. -- Note that synthesis tools like to have latches driven from a -- common enabling signal or clock in the same block. It makes -- for a cleaner model, too. Adder_blk: block signal ZA, ZB, Zout : integer; begin Zc <= Zc_in when ph_2 = '1' else Zc; ZA <= Z1_in when ph_2 = '1' else ZA; ZB <= Z2_in when ph_2 = '1' else ZB; -- Concurrent procedure call to CL_Adder, probably a high level -- model. Phase 1 enables latching the Zsum output. CL_Adder (Z1_in, Z2_in, Zout, Zc); Zsum <= Zout when ph_1='1' else Zsum; end block Adder_blk; -- Z is an output signal, but Zsum can be used -- internally. Z <= Zsum; -- Another concurrent procedure call. Complex -- function determining quadrant of angular -- computations. Compute_Angle ( Zsum, Zang_out, Zang, f, ph_1, s); -- Data_out is driving a bus that may be driven by other units. -- Guarded signal assignment is used here to provide tristate-like -- checking and driving of the bus. Tristate: block ((en = '1') and (ph_1='1')) begin Data_out <= guarded Zsum; end block Tristate; sign_Z <= transport '1' when zsum < 0 else '0'; end Concurrent;
When used for detailed modeling (e.g. the timed behavior of primitive elements), processes provide an algorithmic description for the computation of what may be non-sequential (combinational) logic.
Example
AND_n: process (x) begin Zvar := 1 ; for i in x'range loop if x = '0' then Zvar := 0 ; exit ; end if; end loop; Z <= Zvar after Tprop ; end process AND_n;
The process body executes in an endless loop, interrupted only by WAIT statements; the bottom of the process contains an implicit "go to the top."
Evaluation of a process is caused when one of a list of signals in the wait statement changes value --just as evaluation of a concurrent signal assignment is caused by the change of a value in a condition, select_expression, or waveform.
Just because a process is sequential does NOT mean it is modelling the sequential behavior of a design.
Note that the AND_n process example is the model of a combinational logic element.
TIME DOES NOT ADVANCE within a process; it advances during a WAIT statement.
signal enable : bit := 0; variable vco_freq : frequency := 1 KHz;As long as Tprop, K, load are generics or constants, we can write
Ports can be initialized by
entity xyz port ( a : in bit := '0'; . . . )By providing initial activation of every process in a VHDL model at TIME = 0, it is possible to write the model so the consequences of setting initial values will be completely propagated. Within a process sequential signal assignment statements are always executed when they are encountered, not just when a signal on the right hand side changes.
VVOS <= (not VVRL) and PMR) nor (IOS nand VVRL); PMRS <= IOS or (( not VVRL) and PMR ) ;
However, for synthesis we use the reverse approach. We use the structure associated with concurrent VHDL statements to understand how to synthesize the corresponding sequential VHDL conditional and selected signal assignment statements.
if condition1 then statements elsif condition2 then statements . . . else statements end if;
if memreq = '1' then if read = '1' then memdata <= MEM ( address ); else MEM (address) <= memdata; end if; end if;(We assume here that memreq and read are type BIT, not BOOLEAN.)
We do not show the full structure of the memory referencing activity here. Indexing is a complex special synthesis action which we will need to treat separately later. Note that it implies decoding logic to select an element out of an entire array, and will probably be synthesized by careful partitioning of the decoding address into multiple decoding blocks if the size of the array is large. Such decoding logic may occupy half the space of a large memory chip.
case selector is when value => statements when value |value => statements when discrete_range => statements when others => statements end case ;
case new_val is when '0' => y_out <= '1' after tph; when '1' => y_out <= '0' after tpl; when 'X' => if old_value /= '1' then y_out <= 'X' after tpl; else y_out <= 'X' after tph; end if; end case;
case new_val is when '0' => y_out <= '1' ; when '1' => y_out <= '0' ; when 'X' => y_out <= 'X'; end case;
y_out <= not new_val (1) and new_val (0); y_out <= not new_val;
Rev. 9/6/95 B. Huey