Thursday, August 21, 2008

Still have a lot to learn

Sometimes I ask myself why I am still not posting anything about DSP. DSP has been my most loved subject in school. I have this strong feeling that there's something in it. I don't know what that something is but I want to find it out. However, I didn't learn anything from the class and almost flunked it. But the feeling is still there. There are a lot of books that explains about it but my problem with them is that there are too many dumb equations because I can't understand what they are telling me. When I come across FPGA, I tried to search about its applications. I was so thrilled to see that dsp is one of them. I thought that maybe fpga can help me see beyond those equations and understand the concept behind them. If I can make it help me visualize what the equation parameters do to a certain phenomena, then I will better understand the power of dsp and manipulate the math. The drive is so much I cannot ignore it. Until I watched the movie Babe and heard the narrator say, "But farmer Hogget knew that little ideas that tickled and nagged and refuse to go away should never be ignored for in them lie the seeds of destiny."


Yeaaaaaaah..I still have a lot to learn and the things I post here may seem little steps. But they will take me there. DSP is hard. It becomes much harder when you code it in hardware. I think I must master fpga first and insert some math, and more math and complicated math and more complicated math..until I reach dsp. Takes long time, eh? But still I will take these teeny-weeny steps. At least they keep me moving forward...

Wednesday, August 20, 2008

VHDL Part 31 : VHDL Part 30's warnings

I am now using ISE version 10.1..I had encountered some warnings in the previous version that were just bugs but already cured in 10.1.

Please see VHDL Part 30 for the code.

The synthesis of MUX code I had posted previously completed successfully. However, it gave me the following warnings on the Transcript subwindow (subwindow at the bottom):
(1) WARNING:Xst:819 - "C:/Xilinx/10.1/tahder/scratch/mux1/mux1.vhd" line 44: One or more signals are missing in the process sensitivity list. To enable synthesis of FPGA/CPLD hardware, XST will assume that all necessary signals are present in the sensitivity list. Please note that the result of the synthesis may differ from the initial design specification. The missing signals are:
(2) WARNING:Xst:737 - Found 2-bit latch for signal . Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.

Some people ignore warnings since the design still runs during simulation. I don't as they warn :) me of some problems that might occur during my synthesis. By 'synthesis' I mean when you implement this on the FPGA board. Some warnings are okay, while some can be removed as in the case with this code. To view full info on the warning, see the Design Summary (if not already open, double click View Design Summary on the Processes Subwindow, the one with the green upper case sigma icon).

Here's how I removed those warnings.

(1) Guided by the Design summary, the inputs mux_in1, mux_in2, mx_in3 and mux_in4 must be included in the process sensitivity list. The process line must be

mux_process : process (mux_sel, mux_in1, mux_in2, mux_in3, mux_in4)

(2) This error is explained by Xilinx as stated above. Remember that latches are not clocked and this may lead to synthesis problems. The two-bit latch that were generated are due to the following lines were mux_out2 are not specified.

when "10" => mux_out1 <= mux_in3;
when "11" => mux_out1 <= mux_in4;

If you still decide to go on with simulation in spite of this warning you will have the following result:
Notice mux_out2 values enclosed by the two markers, between times (200ns and 300ns) and (800ns and 900ns). The selector mux_sel has the same value for both time ranges ("11") but they have different mux_out2. That is also what happened with the value of mux_out2 between times (100ns and 200ns) abd (1100ns and 1200 ns) when mux_sel is "10". The reason for this is that the two values of mux_sel ("10" and "11") do not have any mux_out2 specified for them. And so they will just take the value of whatever specified mux_out2 that precedes them. Notice that the mux_out2 for mux_sel "00" and "01" are specified. Whenever these two ("00" and "01") precedes the other ("10" and "11"), the latter two will just take the mux_out2 of the former two.

The way I get around this is that I assign values for all outputs. However, if I don't want to be specific with some of them and I just don't care what their outputs are, use 'X' which is for assigning all unknown or don't care values. And so the case statement must be

when "00" => mux_out1 <= mux_in1; mux_out2 <= "0011";
when "01" => mux_out1 <= mux_in2; mux_out2 <= "0010";
when "10" => mux_out1 <= mux_in3; mux_out2 <= (others=>'X');
when "11" => mux_out1 <= mux_in4; mux_out2 <= (others=>'X');
when others =>

And my simulation result is


which is what I expected.

Going back to the case statement, I may assign "XXXX" to mux_out2 which is a bit vector. However, if the length of my vector is something like 256, using (others=> ) will be very handy.

Also, you may notice the last two lines

when "11" => mux_out1 <= mux_in4; mux_out2 <= (others=>'X');
when others =>

You may say that since there are only 4 possible inputs, why don't I just put these two in one line.

when others => mux_out1 <= mux_in4; mux_out2 <= (others=>'X');

Well, I did it to be sure during synthesis. I may also do something like

when "11" => mux_out1 <= mux_in4; mux_out2 <= (others=>'X');
when others => mux_out1 <= (others=>'0'); mux_out2 <= (others=>'X');

which is also okay (for me).

;)

References:
(1) Pedroni, V., Circuit Design with VHDL, The MIT Press, 2004.
(2) Xilinx MUX Toolbox

VHDL Part 30 : Multiplexer

I need multiplexer too for the current ____ generator I'm working on so I must learn it. A multiplexer, commonly known as MUX, is used when out of several inputs, there can only be one output. To choose the between inputs, a selector is needed. In implementing a MUX in vhdl, care must be taken in order not to generate unintended gates. You may check the results, especially the warnings generated after synthesizing your design (by double clicking Synthesize-XST in the Processes subwindow).

A sample code is
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity mux1 is
generic (muxLen : natural := 4);
port(
mux_in1 : in std_logic_vector (muxLen-1 downto 0);
mux_in2 : in std_logic_vector (muxLen-1 downto 0);
mux_in3 : in std_logic_vector (muxLen-1 downto 0);
mux_in4 : in std_logic_vector (muxLen-1 downto 0);
mux_sel : in std_logic_vector (1 downto 0);
mux_out1 : out std_logic_vector(muxLen-1 downto 0);
mux_out2 : out std_logic_vector(muxLen-1 downto 0)
);
end mux1;

architecture Behavioral of mux1 is
begin

mux_process : process (mux_sel)
begin

case mux_sel is

when "00" => mux_out1 <= mux_in1; mux_out2 <= "0011";
when "01" => mux_out1 <= mux_in2; mux_out2 <= "0010";
when "10" => mux_out1 <= mux_in3;
when "11" => mux_out1 <= mux_in4;
when others =>

end case;
end process mux_process;
end Behavioral;
----------------------------------------------------------------------------------

The code above did not generate errors but there are 2 warnings which will be discussed on the next post. Shown below is the result of my simulation.


References:
(1) Pedroni, V., Circuit Design with VHDL, The MIT Press, 2004.
(2) Xilinx MUX Toolbox

Tuesday, August 19, 2008

VHDL Part 29 : Priority Encoder

I needed a decoder. Since there are a variety of ways to do it, I needed to know which one is best. By 'best' I mean the one that generates lesser number of logic gates at the fastest speed possible. i had learned though, that there is a trade-off between speed and area. The operation of an encoder is inverse to that of a decoder. An encoder has (2**n) input bits and n output bits. The functionality of an encoder is such that only one bit in the input must have a '1' and the rest, '0'. Problem is, if I have other bits in the input which has a value of '1'. A way I get around this is by assigning a priority to each of the input bits. This way, the code cares only about the highest priority (as seen on the index value) and not on other bits in the input. Shown below is a sample code.

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity encode1 is
port(
enc_in : in std_logic_vector (3 downto 0);
enc_out : out std_logic_vector(1 downto 0)
);
end encode1;

architecture Behavioral of encode1 is
begin

enc_out <= "11" when enc_in(3) = '1' else
"10" when enc_in(2) = '1' else
"01" when enc_in(1) = '1' else
"00";

end Behavioral;
----------------------------------------------------------------------------------

Simulation

Shown below is my simulation result. As can be seen, when all bits of my input has a value of '1', since my MSB of the input has the highest priority, the first line of code in the architecture body was executed.


References:
(1) Pedroni, V., Circuit Design with VHDL, The MIT Press, 2004.
(2) Xilinx Priority Encoder Toolbox

VHDL Part 28 : Comparator using when-else statement

Here, another way of implementing concurrent statements is introduced. The comparator in the previous post VHDL Part 27 is implemented using when-else statements.

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity compare1 is
generic (compWidth : natural := 8);
port(
clk : in std_logic;
rst : in std_logic;
comp_in1 : in std_logic_vector (compWidth-1 downto 0);
comp_in2 : in std_logic_vector (compWidth-1 downto 0);
comp_out1 : out std_logic;
comp_out2 : out std_logic;
comp_out3 : out std_logic;
comp_out4 : out std_logic;
);
end compare1;

architecture Behavioral of compare1 is
begin

comp_out1 <= '1' when comp_in1 = comp_in2 else '0';
comp_out2 <= '1' when (comp_in1 >
comp_in2) else '0';
comp_out3 <= '1' when comp_in1 > comp_in2 else '0';
comp_out4 <= '1' when comp_in1 /= comp_in2 else '0';


end Behavioral;
----------------------------------------------------------------------------------

References:
(1) Pedroni, V., Circuit Design with VHDL, The MIT Press, 2004.

VHDL Part 27 : Comparator using if-then-else

The circuit code I had shown below compares two inputs. I have four outputs. The appropriate output gives a high signal whenever the corresponding condition is satisfied. I need this for matching.

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity compare1 is
generic (compWidth : natural := 8);
port(
clk : in std_logic;
rst : in std_logic;
comp_in1 : in std_logic_vector (compWidth-1 downto 0);
comp_in2 : in std_logic_vector (compWidth-1 downto 0);
comp_out1 : out std_logic;
comp_out2 : out std_logic;
comp_out3 : out std_logic;
comp_out4 : out std_logic;
);
end compare1;

architecture Behavioral of compare1 is
begin
process (clk, rst)
begin

if rst = '1' then

comp_out1 <= '0';
comp_out2 <= '0';
comp_out3 <= '0';
comp_out4 <= '0';

elsif
clk'event and clk = '1' then

if
comp_in1 = comp_in2 then

comp_out1 <= '1';
comp_out2 <= '0';
comp_out3 <= '0';
comp_out4 <= '0';

elsif
comp_in1<
comp_in2 then

comp_out1 <= '0';
comp_out2 <= '1';
comp_out3 <= '0';
comp_out4 <= '0';

elsif
comp_in1 > comp_in2 then

comp_out1 <= '0';
comp_out2 <= '0';
comp_out3 <= '1';
comp_out4 <= '0';

elsif
comp_in1 /= comp_in2 then -- not equal

comp_out1 <= '0';
comp_out2 <= '0';
comp_out3 <= '0';
comp_out4 <= '1';

end if
;
end if;
end process;
end Behavioral;
-----------------------------------------------------------------

The circuit above could be easily implemented using when-else statement. However, I want the outputs to be synchronized with the clock.

References:
(1) Pedroni, V., Circuit Design with VHDL, The MIT Press, 2004.


VHDL Part 26 : Decoder

Although I had already implemented a decoder in VHDL Part 20, it is worth tackling this circuit once more. I had shown below a sample code. I need a decoder for the current ___ generator I'm working on. Sorry guys, I can't tell you about it.

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity decode1 is
generic (decWidth : natural := 8);
port(
clk : in std_logic;
rst : in std_logic;
dec_in : in std_logic_vector (1 downto 0);
dec_out : out std_logic_vector(decWidth-1 downto 0)
);
end decode1;

architecture Behavioral of decode1 is
begin
process (clk, rst)
begin

if rst = '1' then

dec_out <= (others => 'Z');

elsif clk'event and clk = '1' then

case dec_in is

when "11" => dec_out <= "01100001"; -- a
when "10" => dec_out <= "01100011"; -- c
when "01" => dec_out <= "01110100"; -- t
when others => dec_out <= "01100111"; -- g
end case;
end if;
end process;
end Behavioral;
----------------------------------------------------------------------------------
The circuit I had used has two typical one-bit inputs clk and rst. Another input
dec_in (2 bits) is used to select which of the four bit vectors must be passed to the output port dec_out(8 bits). The output may represent any of the four letters a, c, t and g. The selector dec_in is represented by only two bits because there are only four possible outputs (2**2 = 4). The 8-bit vectors are the ASCII representation of the letters.

VHDL Part 25 : Accumulator

In an accumulator, the destination and first operand is a signal or variable, and the second operand is either another signal or variable or a constant not equal to 1.
- Xilinx

The statement above actually expresses the difference between a counter and an accumulator. A counter increments a signal or variable only by 1. With accumulator I can increment a signal/variable with any number. I had modified the counter code in VHDL Part 13 to implement an accumulator in VHDL. Special thanks to Xilinx toolbox for their tutorial on this. Link is at the bottom of this page

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity accu1 is
generic (accuWidth : natural := 4);
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
accuEn : in STD_LOGIC;-- enable
accu_in : in STD_LOGIC_VECTOR (accuWidth-1 downto 0);
accu_out : out STD_LOGIC_VECTOR (accuWidth-1 downto 0));
end accu1;


architecture Behavioral of accu1 is

begin

process (rst, clk)

-- note that we can have a bit vector for a variable
variable accu_v : STD_LOGIC_VECTOR (accuWidth-1 downto 0);

begin

-- async reset
if rst = '1' then

-- initialize the output and the variable to "0..."
accu_out <= (others=>'0');
accu_v := (others=>'0');

elsif
clk'event and clk = '1' then
if accuEn = '1' then

accu_v := accu_v + accu_in;

end if;
end if;
accu_out <= accu_v;
end process;
end Behavioral;
------------------------------------------------------------------

Reference:
(1) Xilinx Accumulator Toolbox

VHDL Part 24 : Boolean in VHDL

I had seen a lot of times that boolean types were used in generic declarations. I wonder where to use the boolean types so I did a little study that would eventually help me when to use it. my reference is cited at the bottom of this post.

In VHDL, Boolean types are enumerated types. It can only take two values: true and false. Of course, this does not have any width. It can be the result of any logical operation (or, nor, and, nand, xor, not) in an if statement for instance. It can also be assigned to a similar data type to express a logical state.

logicalState <= booleanValue;

Reference:
(1) Pellerin, D. and Taylor, D., VHDL Made Easy, Prentice Hall PTR, 1996.

VHDL Part 23 : Exiting the Loops

There are also two ways with which the user can exit a loop.

(1) next

The next statement terminates the execution of a loop and jumps to another iteration if a condition is met. Shown below is the syntax.

-----------------------------------------------------------------------------------------
loop_label : for loop_indentifier in loop_range loop -- example: for i in 4 downto 0 loop

sequential_code

next when exit_condition; -- example: next when i = 1;

sequential_code

end loop loop_label;
-----------------------------------------------------------------------------------------

(2) exit

The exit statement, when a condition is satisfied, terminates the execution of whatever the loop is currently doing and terminates the loop itself. It does not jump to any other iteration. Shown below is the syntax.

-----------------------------------------------------------------------------------------
loop_label : for loop_indentifier in loop_range loop -- example: for i in 4 downto 0 loop

sequential_code

exit when exit_condition; -- example: exit when i = 1;

sequential_code

end loop loop_label;
-----------------------------------------------------------------------------------------

Reference:
(1) Pedroni, V., Circuit Design with VHDL, The MIT Press, 2004.

VHDL Part 22 : VHDL Loops

Two loops used in software are also available in VHDL. Loops are sequential so it can be included in a process.

(1) for-loop

The for-loop is used if the designer knows when the loop must end. Syntax is shown below.

---------------------------------------------------------------------
loop_label : for loop_indentifier in loop_range loop

sequential_code

end loop loop_label;
---------------------------------------------------------------------

The loop_range can be expressed as to or downto. See this VHDL Part 12.

loop_label(s) are good for debugging especially if you have several loops in the code.

(2) while-loop

While loop is employed if the designer does not know when the fixed number of iteration a loop must perform. He only knows the condition that must be met in order to get out of the loop. Since while-loops is not usually employed in the codes that you will see here, I will be very shallow with this. Syntax is shown below.

---------------------------------------------------------------------
loop_label : while loop_condition loop -- example : while (j <>

sequential_code

end loop loop_label;
---------------------------------------------------------------------

Reference:
(1) Pedroni, V., Circuit Design with VHDL, The MIT Press, 2004.

VHDL Part 21 : Counter with Seven-Segment Display

This time I had learned to connect the counter on VHDL Part 19 and the Seven-Segment Display driver on VHDL Part 20.

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter_SSD is
generic (cOutWidth : natural := 4;
sOutWidth : natural := 7);
port (clk : in STD_LOGIC;
rst : in STD_LOGIC;
set : in STD_LOGIC;
dispEn : in STD_LOGIC;
disp_out : in STD_LOGIC_VECTOR (sOutWidth-1 downto 0));
end counter_SSD;

architecture Behavioral of counter_SSD is

component counter3
-- note the declaration of generic statement in component instantiation
generic (cOutWidth : positive);
port (
clk : in STD_LOGIC;
rst : in STD_LOGIC;
set : in STD_LOGIC;
countEn : in STD_LOGIC;
count_out : in STD_LOGIC_VECTOR (coutWidth-1 downto 0));
end counter3;

component SSD
-- note the declaration of generic statement in component instantiation
generic (cOutWidth : positive;
cOutWidth : positive);
port (SSD_in : in std_logic_vector (sInWidth-1 downto 0);
SSD_out : out std_logic_vector(sOutWidth-1 downto 0) );
end SSD;

-- this is for the internal connection of the two components
-- note that we are trying to connect the output port of counter3 to the input port of SSD
signal count_s : std_logic_vector (cOutWidth-1 downto 0);

begin

counter : counter3
-- map the generic statement of counter3 to the generic statement of the topblock
-- note the mapping operator => which is very much different to the assignment operator =>
-- it is fine that to map a generic with a generic that has the same name
generic map (cOutWidth => cOutWidth);

-- likewise, it is fine that to map a port with a port that has the same name
-- note that commas separate the port maps
port map (clk=>clk,
rst=>rst,
set=>set,
countEn=>dispEn,
count_out=>count_s);

display : SSD

generic map (sInWidth =>cOutWidth,
sOutWidth=>sOutWidth);

port map (SSD_in=>count_s,
SSD_out=>disp_out);

end Behavioral;
----------------------------------------------------------------------------------

I had labeled each of the two components. This is very useful in my simulations so that when an error or a warning is generated, the component that causes that error or warning is easily identified by the simulator. It will then be easy for me to debug it.

The simulator will look for the source codes of the two components that were instantiated. See VHDL Part 6 for a post on how to add the source codes into the project.

VHDL Part 20 : Seven Segment Decoder

I had shown below the code that I use for seven segment display (SSD) decoder. I need to use this so that I can display the outputs of previous post on a sevent-segment LED.

Please note that the output SSD_out can change depending on the seven segment display you are using.

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity SSD is
generic (sInWidth : natural := 4;
sOutWidth : natural := 7);
port(SSD_in : in std_logic_vector (sInWidth-1 downto 0);
SSD_out : out std_logic_vector(sOutWidth-1 downto 0) );
end SSD;

architecture Behavioral of SSD is
begin
process (SSD_in)
begin

case SSD_in is
-- change SSD_out based on the configuration of the seven-segment you are using
-- kindly check the specs

when "0010" => SSD_out <= "0010010"; -- 2
when "0011" => SSD_out <= "0000110";
when "0100" => SSD_out <= "1001100";
when
"0101" => SSD_out <= "0100100";
when
"0110" => SSD_out <= "0100000";
when "0111" => SSD_out <= "0001111";
when "1000" => SSD_out <= "0000000";
when
"1001" => SSD_out <= "0001100"; -- 9
when "1010" => SSD_out <= "0001000";-- A
when "1011" => SSD_out <= "1100000";
when
"1100" => SSD_out <= "0110001"; -- C
when others => SSD_out <= "1111110"; -- '-'
end case;
end process;
end Behavioral;
----------------------------------------------------------------------------------

Reference:
(1) Pedroni, V., Circuit Design with VHDL, The MIT Press, 2004.

VHDL Part 19 : Counter with integer to std_logic_vector Converter

I learned to implement a counter but this time the input and output ports are bit vectors. I had done this with the goal of eventually connecting this to a seven segment decoder. This is so that I can use a seven segment display as an output device.

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter3 is
generic (coutWidth : natural := 4);
port(clk : in STD_LOGIC;
rst : in STD_LOGIC;
set : in STD_LOGIC;
countEn : in STD_LOGIC;
count_out : in STD_LOGIC_VECTOR (coutWidth-1 downto 0));
end counter3;

architecture Behavioral of counter3 is
begin

process (clk, rst, set, countEn)

variable count_v : integer range 0 to 15;

-- start_c is default, we want this to be the number the counter will start with
constant start_c : integer range 0 to 15 := 3;

begin
if rst = '1' then
count_v := 0;
elsif clk'event and clk = '1' then
if countEn = '1' and set = '1' then
count_v := start_c;
elsif countEn = '1' and set = '0' then
if count_v = 15 then
count_v := start_c;
else
count_v := count_v + 1 ;
end if;
end if;
end if;

case count_v is
when 0 => count_out <= "0000";
when
1 => count_out <= "0001";
when
2 => count_out <= "0010";
when
3 => count_out <= "0011";
when
4 => count_out <= "0100";
when
5 => count_out <= "0101";
when
6 => count_out <= "0110";
when
7 => count_out <= "0111";
when
8 => count_out <= "1000";
when
9 => count_out <= "1001";
when
10 => count_out <= "1010";
when
11 => count_out <= "1011";
when
12 => count_out <= "1100";
when
13 => count_out <= "1101";
when
14 => count_out <= "1110";
when others
=> count_out <= "1111";
end case
;
end process;
end Behavioral;
----------------------------------------------------------------------------------

Reference:
(1) Pedroni, V., Circuit Design with VHDL, The MIT Press, 2004.

VHDL Part 18 : Initializing signals

I had encountered this warning which you have probably encountered too.

"The application failed to initialize properly..."

One way I get around this is I initialize the signal(s) or variable(s) you used. Syntax is shown below.

signal signal_name : data_type := initial_value;

--------------------------------------------------------------------
signal count_s : std_logic_vector (127 downto 0) := (others => '0');
--------------------------------------------------------------------

This special kind of assignment in which the user assigned an initial value to a signal (or variable or generic or port) is called aggregate assignment. This works only in simulation but not in synthesis. Initial values are commonly ignored by the tool you use for synthesis for reasons that the tool cannot predict that the target board will be triggered in a known state.

References:
(1) Pellerin, D. and Taylor, D., VHDL Made Easy, Prentice Hall PTR, 1996.

VHDL Part 17 : Wait Statements

Wait was introduced in my previous post. Since the sensitivity list is taken away, the wait statement is placed right after the begin of the process. To stress further, it must be the first statement on the body of the process. It takes three forms.

(1)
wait until
condition_here

wait until can take only one signal. As in my previous post, below is the wait statement that was used.

-----------------------------------------------------------------
wait until (clk'event and clk = '1')
-----------------------------------------------------------------

The above syntax of wait makes all the other signal(s) synchronous. Even if only the clk signal is taken by the wait statement, the process will still be sensitive to rst or some other signal(s). It is just that all events will respect the clock.

(2)
wait on signal_1, signal_2, ...

Use wait on if you want to maintain rst (or other signals) as asynchronous. wait on can take several signals. An example is shown below.

-----------------------------------------------------------------
process --no sensitivity list
begin

wait on (rst, clk)
if rst = '1' then

shReg _out <= (others => '0');

elsif clk'event and clk = '1' then
if shiftEn = '1' then

shReg _out <= sh_in & shReg_in (regCount-1 downto 1);

end if;
end if;
end process;
-----------------------------------------------------------------

(3) wait for specific_time

wait for is commonly seen in testbenches. This is good for generating the intended waveforms at a specific time. An example is shown below. This can be a portion of a testbench.

-----------------------------------------------------------------
process --no sensitivity list
begin

rst <= '0'; shiftEn <= '1'; sh_in <= "00011"; wait for 200 ns;

shiftEn <= '0'; wait for 500 ns;

end process;
-----------------------------------------------------------------

Reference:
(1) Pedroni, V., Circuit Design with VHDL, The MIT Press, 2004.

Monday, August 18, 2008

VHDL Part 16 : Forms of Process Statements

Whenever I use if-then-else statements, I use Process statements. This is for me to be able to simulate the response of the output for a change in the inputs it is sensitive to. Process statements can have two forms--with sensitivity list and without.

The codes I had used in the previous posts are processes with sensitivity list. During simulation, these processes execute whenever any signal in my sensitivity list changes.

-----------------------------------------------------------------
process (rst, clk)
begin

if rst = '1' then

shReg _out <= (others => '0');

elsif
clk'event and clk = '1' then
if shiftEn = '1' then

shReg _out <= sh_in & shReg_in (regCount-1 downto 1);

end if;
end if;
end process;
-----------------------------------------------------------------

The other type does not include a sensitivity list. Instead, it employs one or more condition(s) that would postpone the execution of the process until it is met. Although this is not synthesizable, this is good for creating testbench codes. Shown below is a sample code.

-----------------------------------------------------------------
process --no sensitivity list
begin

wait until (clk'event and clk = '1')
if rst = '1' then

shReg _out <= (others => '0');

elsif clk'event and clk = '1' then
if shiftEn = '1' then

shReg _out <= sh_in & shReg_in (regCount-1 downto 1);

end if;
end if;
end process;
-----------------------------------------------------------------

Here, without the sensitivity list, I have to make rst synchronous which is I don't usually do. What will happen is that when rst is high, shReg_out will reset back to "00..." at the next clock cycle. This won't be detrimental to my output(s). I just have to make this synchronous with the clock in order for me to simulate its events.

References:
(1) Pedroni, V., Circuit Design with VHDL, The MIT Press, 2004.
(2) Pellerin, D. and Taylor, D., VHDL Made Easy, Prentice Hall PTR, 1996.

VHDL Part 15 : Behavioral vs Structural Description

I think the knowledge of the difference between behavioral and structural description is very important for a vhdl coder. For my designs, I am fond of using structural coding for topblocks and behavioral for the subblocks. Some of my definitions here are based from my observation while others are form reference cited at the bottom of this post.

Behavioral description of a circuit is the highest level of abstraction in VHDL. Here, the circuit is described in terms of it operation with respect to time. All operations are in one level of code. The operations are described in a way that the designer of a sequential circuit infers a register. The code in VHDL Part 10 is an example of a behavioral code. The code is shown below.

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity shiftReg is
generic (
regCount : natural := n); -- replace n with 4, 5, 8, etc. depends on the number you need
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
shiftEn : in STD_LOGIC;
sh_in : in STD_LOGIC;
shReg _in : in STD_LOGIC_VECTOR (regCount-1 downto 0);
shReg _out : out STD_LOGIC_VECTOR (regCount-1 downto 0));
end shiftReg;


architecture Behavioral of shiftReg is

begin

process (rst, clk)
begin

if rst = '1' then

shReg _out <= (others => '0');

elsif
clk'event and clk = '1' then
if shiftEn = '1' then

shReg _out <= sh_in & shReg_in (regCount-1 downto 1);

end if;
end if;
end process;

end Behavioral;
-----------------------------------------------------------------

Structural description, on the other hand, is a circuit description in terms of its components. it can either create a low level description, much like a hierarchy in a block diagram. Whenever you see a component instantiated in a code, that code employs structural description of the circuit. The components are connected in the form of a netlist. This is for better manageability and reusability. Show below is the code for VHDL Part 6. The code below is a structural description of an n-bit register.

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ckt_reg is
generic (pattern : natural := 4);
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
loadEn : in STD_LOGIC;
reg _in : in STD_LOGIC_VECTOR (regCount-1 downto 0);
reg _out : out STD_LOGIC_VECTOR (regCount-1 downto 0));
end ckt_reg ;

architecture Behavioral of ckt_reg is

component dFF
port (clk, rst, loadEn, D_in : in std_logic;
D_out : out std_logic);
end component;

begin

iFF : for i in 0 to
regCount-1 generate
FF : dFF port map (clk=>clk, rst=>rst, loadEn=>loadEn,
D_in=>reg _in(i), D_out=>reg _out(i));
end generate iFF;

end Behavioral;
-----------------------------------------------------------------

Reference:
(1) Pedroni, V., Circuit Design with VHDL, The MIT Press, 2004.



VHDL Part 14 : 2-digit Counter

My previous post showed one of the codes for a 1-digit counter. I had shown below the code for a 2-digit counter. For this, I will be needing two variables. One for the ones place, the other for the tens. This will emulate a 60-second counter. I cited the reference below.

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity upCounter2 is
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
countEn : in STD_LOGIC;-- enable
count_in : in STD_LOGIC;
count_out1 : out INTEGER RANGE 0 To 6; -- ones
count_out2 : out INTEGER RANGE 0 To 9); -- tens
end upCounter2;


architecture Behavioral of upCounter2 is

begin

process (rst, clk)

variable count_v1 : integer range 0 to 10; -- ones
variable count_v2 : integer range 0 to 6; -- tens

begin

-- async reset
if rst = '1' then

-- initialize the outputs and the variables to 0
count _out1 := 0;
count_v1 := 0;
count _out2 := 0;
count_v2 := 0;

elsif
clk'event and clk = '1' then
if countEn = '1' then

count_v1 := count_v1 + 1;

if count_v1 = 10 then

count_v1 := 0;
count_v2 := count_v2 + 1;

if count_v2 = 6 then

count_v2 := 0;

end if;
end if;
end if;
end if;

count_out1 <= count_v1;
count_out2 <= count_v2;


end
process;
end Behavioral;

-----------------------------------------------------------------

References:
(1) Pedroni, V., Circuit Design with VHDL, The MIT Press, 2004.