Translate

Friday, December 16, 2011

A simple counter

    Counters are very important and you will probably use them in your projects since they are needed in lots of situations. So what do counters do? Very simple: they count. At every clock cycle the value memorized in the counter's memory element is incremented or decremented by 1 and the result is fed to the output port.
    Counter circuits that you can find on the market have different functions like a chip enable input to enable/disable the circuit, parallel load to load a value from the outside and count from there, a port that controls the way it counts (forward or backward). But for the siple projects that we will be designing for now we don't need all those features. All we need is a clock input, a reset input and the data output.
    The value that a counter uses can be of different lengths: 4 bits, 8 bits, 16 bits etc. So when you hear that a counter is a 8 bit counter you will know that the output has 8 bits and so on.
    In this tutorial we will be making a 4 bit bcd counter (it counts from 0000 witch is 0 in decimal to 1001 witch is 9 in decimal). It has of course a 4 bit output for the number and 2 inputs: the clock and the reset.
    How it works: At first the internal value of the counter is 0 so that is what will be at the output. Every clk cycle that value is incremented by 1. Once it reaches 9 (1001), it stays at this value for 1 clk cycle and then goes back to 0. If the reset is activated at any time during the operation of the circuit then the internal value is back at 0.
    Now let's see the code for this counter:


    In order for the code to work you of course have to add the std_logic_unsigned library:
              use IEEE.STD_LOGIC_UNSIGNED.all;

    As you can see it has an asynchronous reset witch when activated resets the cnt variable to all 0s. The output port is refreshed at the end of the process every time.
    Now that we have the code we have to test it. But if we were to put it on the FPGA and connect the clk input to the clock then we wouldn't be seeing results because the clock is to fast (50/100 MHz usually). Let's design a simple test circuit.
    I want this circuit to 1 to the variable every second and display the value on 4 LEDs from the FPGA. For this we will need the clock divider from the previous tutorial in order to obtain a 1 Hz signal from the one that we have (mine is 100 MHz). The output of the divider will connect to the clk input of the counter. This way it is activated every second. The outputs of the counter go directly to 4 LEDs.
    The circuit schematic looks like this:
    So let's begin. To the project with the counter we will add a new entity witch is the divider from the last tutorial. The only difference is that now we want the clko signal to be activated every second, not half a second. For that you just have to double the value used. So for a 50 MHz clock you will use 49000000 and for a 100 MHz clock 99000000.
    Now let's create the main system. As you can tell it has 2 inputs and a 4 bit output:
.
    
    We will need just a signal that connects the clko output from the div circuit to the clk input of the counter.
    Let's see the architecture:
    If you want you can modify this project to use a 7 segment display instead of the LEDs. For this you will need to connect the 7 segment decoder to the output of the counter.
    
    If you want to contact me my e-mail is fpgatutorials@gmail.com
    Feel free to leave me suggestions or comments.
    Thank you for reading.
    

    
 

Thursday, December 8, 2011

Synchronization in sequential circuits (clock dividers)

    Oscillators and frequency
    A very important component of any FPGA development board is the crystal oscillator. The oscillator emits a sequence of 0,1 at a given time based on it's frequency. Oscillators are used in lots of electronic devices like TVs, radios, cell phones, computers and others. For example when you buy a PC or a processor and you read that it's frequency is 2 GHz (gigahertz) it means that the oscillator has a frequency of 2 GHz. It means that the oscillator emits 2 billion sequences of 0,1 signals.
    Frequency can be used to measure time as well. The formula to transform from frequency in time is:
   
    f=1/T
   
    T is the period and it's measured in seconds and frequency is measured in hertz.
    1 Hz is equal to 1 second (1=1/1).
    A 1 Hz signal i represented like so:

    If you want to read in more detail about oscillators you can read the Wikipedia article.

    Synchronization
    Though we haven't used it yet, almost all FPGA projects use the oscillator either for synchronization of different circuits or in order to use some I/O circuits like the serial port or the VGA port. The signal we get from the oscillator is called a clock signal and abbreviated clk in code. Synchronization is important because in complex designs it assures you that commands are not executed in arbitrary mode by the components of the main circuit. Xilinx recommends synchronizing signals where you can and using asynchronous signals only if necessary.
    Example of a register  using synchronous signals and asynchronous signals:

              process(clk)
              begin
                  if(clk'event and clk='1') then
                      if(reset='1') then
                          data_out<=(others=>'0');
                      else
                          data_out<=data_in;
                      end if;
                  end if;
              end process;

    This is the synchronous design. as you can see in the first if the clk signal is tested. The 'event keyword is used in order to see if a signal changed it's value (from 0 to 1 or from 1 to 0) and then we see if with the event on the signal it's value is now 1. You can test if clk='0' if you want but it's advised to use non inverted logic.
    clk'event and clk='1' can be written as rising_edge(clk) and clk'event and clk='0' can be written as falling_edge(clk).
    In this process all actions are synchronized with the clk signal. This means that if the clk hasn't changed it's value to 1, the other statements are not executed.
    You can tell that this circuit is synchronized from 2 things:
       - the sensitivity list of the process contains only the clk signal so it's executed only when it changes it's value
       - all the other statements are inside the first if. This means that the state of the clk controls the other signal tests and assignments. This is why when using lots of circuits synchronized with the same clk the signals won't be assigned as random signals change their values.

    Let's see the same circuit but now with an asynchronous reset signal:

              process(clk,reset)
              begin
                   if(reset='1') then
                      data_out<=(others=>'0');
                  elsif(clk'event and clk='1') then
                      data_out<=data_in;
                  end if;
              end process;

    As you can see the process is executed now when clk changes it's value or when reset changes it's value. The reset is checked first and if it's 1 then the register will be reset. If the reset is not active then the clk signal is tested. 
    I recommend using the first design.

    Clock dividers
    These circuits are important because you will usually need more than 1 clock signal in a design. For example consider you have the global clock of your board at 50 Mhz and you will use it to design a VGA port and a serial port. In order to use these peripherals you will need a 25 MHz clock for the VGA and usually a 9,6 KHz clock for the serial port. You will need 2 clock dividers in order to obtain the 2 frequencies needed.
    Often you will want to count time like seconds or milliseconds. In order to do this you need to divide the clock so that you get the frequency resulted from the formula from the beginning of the tutorial.
    f=1/T
    It is advised to use the hertz and seconds for f and T in order to avoid any mistakes.

    Time conversions:
    1 millisecond=0.001 seconds
    1 microsecond=0.000 001 seconds
    1 nanosecond=0.000 000 001 seconds

    Basic frequency-time conversion:
    1 Hz <=> 1 second
    10 Hz <=> 0.1 seconds
    100 Hz <=> 0.01 seconds
    1 KHz (1 000 Hz) <=> 1 millisecond
    1 MHz (1 000 000 Hz) <=> 1 microsecond
    1 GHz (1 000 000 000 Hz) <=> 1 nanosecond

    These 2 tables are important when you want to check that you made the right division for obtaining a certain time. 
    Let's take an example: Been given a dev board with the global clock of 100 MHz, divide it so that a LED of the board is on half a second and off the other half. 
    First we need to calculate the frequency needed using the formula:
    f=1/0.500=2 Hz
    0.500 seconds or half a second is equal to 2 Hz.
    The type of divider we will implement is a counting divider so we need a constant to count witch is calculated as so:
    c=gclk/clk
    gclk is the global clock frequency and clk is the desired frequency so the constant is:
    c=100 000 000/2=50 000 000
    So each time the global clock changes it's value and is 1 we increment the counter and when it reaches 50 000 000 or 49 000 000, depending on the design used, the clk signal gets the value 1. For any other variables the clk will be 0.

    Now it's time to design the circuit. It has 2 inputs (clk and reset) and one output (clko).

    Now let's see the process:

    As you can see this circuit is synchronized with the clk signal. The variable cnt is used to count the clock signals so that we can divide it. I recommend using the type std_logic_vector for the variable type. It's 26 bits in width because you need 26 bits in order to form the number 49 000 000. In order to see the number of bits a number is formed with you can write it in the Calculator application from Windows and then select View->Programmer and check Bin. The number will be converted to binary.
    When reset is active the variable gets the value 0 and the output clock is 0. As cnt is incremented, the output clock stays 0 but when it reaches the value needed, the output clock will be 1.
    In order to use the + on std_logic_vector types you need to include a new library:

    use IEEE.STD_LOGIC_UNSIGNED.ALL;

    A test circuit
    Let's continue the example. Now that we have the divided clock we need to link it to the circuit which controls the LED. 
    A diagram of the circuit:
    The led_driver represents a process that has an asynchronous reset input and the divided clk input. The output connects to the LED.
    Let's start. Create another VHDL module in the project and declare the div component in it. We will also declare a signal that links the output of the div circuit to the driver.
    
    Let's see the architecture body:
    

    The led output is connected to the l variable. When reset is 1, l gets the value 0. When the divided clk changes it's value in 1, l is inverted so that the LED is on half a second and then off the other half and so on.