If you are seeing this message you are either a guru who has a custom browser setting, or your browser is out of date and cannot handle some of the more recent Web standards. In our opinion this site would look much better with the standard setup of a modern browser. However we intend it to be accessible to any browser or Internet device.

 

  |   home  |   products  |   support  |   FAQ  |   free stuff  |   design services  |   contact  |  

you are here: home > free stuff

This page holds some pieces of code which could be useful to designers working in VHDL, particularly applied to FPGAs.

LED Flasher with Varying Intensity

This code generates a flashing LED signal with an intensity which rises smoothly from 0% (off) to 100% (fully on). In this example, each intensity cycle contains 32 intensity levels and the code ticks through the levels at the rate of 150Hz, giving an overall flash rate of approximately 5Hz.

First we generate a 150Hz Tick signal from the master clock:

-- divide the main clock down to approx 150Hz
constant CLOCK_RATE: integer := 25*1000*1000;
constant TICK_RATE : integer := 150;
constant FREQ_DIV  : integer := CLOCK_RATE/TICK_RATE;

signal Counter: integer range 0 to FREQ_DIV;
signal Tick : boolean;

process (clk)
begin
  if rising_edge(clk) then
    if Counter=0 then
      Counter <= FREQ_DIV;
    else
      Counter <= Counter-1;
    end if;
    Tick <= Counter=0;
  end if;
end process;

Then generate a saw-tooth incrementing Delta register which wraps round to 0.

-- set B=5 forces 32 intensity levels
constant B: integer := 5;
signal Delta : unsigned(B-1 downto 0);

process (clk)
begin
  if rising_edge(clk) then
    if Tick then
      Delta <= Delta+1;
    end if;
  end if;
end process;

Now we can generate LedOn - the LED PWM signal.

-- Accum is the phase accumulator for the PWM
signal Accum : unsigned(B downto 0);
signal LedOn : boolean;

process (clk)
  variable Acc, Delt: unsigned(Accum'range);
begin
  if rising_edge(clk) then
    if Tick then
      Accum <= (others=>'0');
    else
      Acc := '0' & Accum(B-1 downto 0); -- clear overflow to zero
      Delt:= '0' & Delta;               -- bit-extend with zero
      Accum <= Acc + Delt;
    end if;
    LedOn <= (Accum(B) = '1');          -- overflow drives LED
  end if;
end process;

Locking Logic to a Single Xilinx Virtex LUT

How do you constrain HDL logic so that it is mapped to a single LUT in a Xilinx Virtex or Virtex-E part? This package lets you define your VHDL logic like this:

signal a,b,c,d,x : std_logic;

LU: VLut4 generic map ( ExprStr => "((I0*I1)@(I2*~I3))" )

       port map (I0=>a, I1=>b, I2=>c, I3=>d, O=>x );

This evaluates the following expression:

x <= (a and b) xor ( c and (not d));

Cautions:

Here is the VHDL package and components to download : VirtexLut.vhd

VHDL Version of itoa()

A VHDL equivalent to the itoa() function in C is sometimes needed in testbench code and in attribute string generation. This is a simple recursive implementation of itoa(). The local variable n (see below) is not technically necessary.

type TStr10 is array (0 to 9) of string(1 to 1);

constant Str10: TStr10 :=

    ("0","1","2","3","4","5","6","7","8","9");

 

function itoa( x : integer ) return string is

  variable n: integer := x; -- needed by some compilers

begin

  if n < 0 then return "-" & itoa(-n);

  elsif n < 10 then return Str10(n);

  else return itoa(n/10) & Str10(n rem 10);

  end if;

end function itoa;

The function has been tested for integers up into the thousands. It probably will not give the correct answer with integers which use 32 bits or more of precision.