Gray-counter n-bit wide

A very interesting approach is: http://www.isibrno.cz/~ivovi/gray_counter.pdf

Ing. Ivo Viščor, in his 2nd year of PhD study described a universal aproach in VHDL.

 

He uses the concept of a component, a very useful construct in VHDL. It is like making a printed circuit board, a PCB. On a typical PCB (not on a PCB with CPLD’s of course) you will find a lot of logic chips. Some are of the same type.

 

In VHDL you can define a logic package and use it in different places. That is what you can do with a component, Ivo defined a logic building block, gray_1, and used it to construct a gray-counter for n bits.

 

Let us try that with the Project Navigator.

Create gray_1.vhdl

Define a new project with a vhdl-model named gray_1.

If you  don’t specify anything you get a template like this:

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

 

--  Uncomment the following lines to use the declarations that are

--  provided for instantiating Xilinx primitive components.

--library UNISIM;

--use UNISIM.VComponents.all;

 

entity gray_1 is

end gray_1;

 

architecture Behavioral of gray_1 is

 

begin

 

 

end Behavioral;

 

Edit the source-text to look like:

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

 

entity gray_1 is

    Port ( arst : in std_logic;

           clk : in std_logic;

           qin : in std_logic;

           zin : in std_logic;

           qout : inout std_logic;

           zout : out std_logic);

end gray_1;

 

architecture Behavioral of gray_1 is

 

begin

  process(arst, clk)

    begin

      if arst = '1' then

        qout <= '0';

      elsif clk'event and clk = '1' then

        qout <= qout xor (qin and zin);

      end if;

    end process;

 

    zout <= zin and not qin;

 

end Behavioral;

 

Now we have defined our building block gray_1. With that we can make an n-bit wide gray-counter. Don’t forget to save your work before going on with gray_n.

Create gray_n.vhdl

 Click on New Source in the process pane at the lower left of the screen. Give it a name gray_n, don’t specify anything more and click finish. Again you get a template file like this:

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

 

--  Uncomment the following lines to use the declarations that are

--  provided for instantiating Xilinx primitive components.

--library UNISIM;

--use UNISIM.VComponents.all;

 

entity gray_n is

end gray_n;

 

architecture Behavioral of gray_n is

 

begin

 

 

end Behavioral;

 

Edit this template to look like this:

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

 

entity gray_n is generic (width: integer :=3);

    Port ( async_rst : in std_logic;

           clock : in std_logic;

           q : inout std_logic_vector(width downto 0));

end gray_n;

 

architecture archgray_n of gray_n is

  component gray_1 port ( arst, clk, qin, zin : in std_logic;

                            qout: inout std_logic;

                            zout : out std_logic);

  end component;

 

signal z : std_logic_vector(width downto 0);

signal qx : std_logic;

begin

  create_lsb: for i in 1 to width-1 generate

    createbit: gray_1 port map(  async_rst, clock,

                                 q(i-1), z(i-1),

                                 q(i), z(i));

    end generate;

  create_msb: gray_1 port map(   async_rst, clock,

                                 qx, z(width-1),

                                 q(width),z(width));

  qx <= q(width-1) or q(width);

 

  process(async_rst, clock)

  begin

    if async_rst = '1' then

      q(0) <= '1';

    elsif clock'event and clock = '1' then

      q(0) <= not q(0);

    end if;

  end process;

 

  z(0) <= '1';

end archgray_n;

 

The component declaration (in red for clarity) tells about the existence of a definition of gray_1.vhdl.

 

Again save your work before doing anything else. If you save this file the Project Navigator will automagically adjust the hierarchy of the source files!

 

Doubleclick on “implement design” in the process pane. Correct eventual errors.

Simulate the design

It is always wise to test a design before even “burning” it in a CPLD. It is possible to define a set of input-signals and a set of expected output-signals. The simulator can pin-point errors in the design. I won’t describe that procedure here, just because I don’t feel an expert in this field. I am only beginning to understand matters…

 

To create a test waveform simply double click on “Create New Source” and select “Test Bench Waveform”. Call your file gray_n_wave and associate this file with gray_n.. Click OK in the first screen with the title “Initialize timing” and go and edit the wave forms.

Make async_rst ‘1’ for two clock cycles. If you right-click on the clock you can set the end of the testbench to, say 2000 ns. Save your work.

 

Now there is a file gray_n_wave.tbw in the file hierarchy. With this file selected double-click on “Simulate Behavioral VHDL Model”. ModelSim will be launched a simulates the gray-counter. Zoom in on the results and enjoy!

 

Your output should look somehow like this:

 

 

As you can see q(0) is the parity bit. Of course it toggles every clock cycle because with Gray-code only 1 bit a time changes.

 

Wageningen, 19 april 2004 de PA1KDG