Xilinx Schematic design vs VHDL code design

Z

ZackS

I am currently using Xilinx Project Navigator to do some VHDL programming.
I have created a cicuit using both my own VHDL code and using a schematic
on the Xilinx ECS program. My VHDL code seems to be faster than the
schematic code (when I use the synthesis report), but uses more devices.
For example, one of my programs written as VHDL code produces
8 slices
10 flip flops
11 LUTs
9 IOBs
2 GCLKs
The minumum period is 3.991 ns (250 MHz)

When the same device was written with the schematic program it produced
8 slices
8 flip flops
0 LUTs
10 IOBs
1 GCLK

but the minumum period is 5.979 ns (167 MHz)

Has anyone done any research into why hand written VHDL is faster but uses
more devices? I am really interested in why my VHDL code is faster than
the schematic code. Any information that anyone can give me would be
great
 
J

Jerker Hammarberg (DST)

Hi!
I am currently using Xilinx Project Navigator to do some VHDL
programming. I have created a cicuit using both my own VHDL code and
using a schematic on the Xilinx ECS program. My VHDL code seems to be
faster than the schematic code (when I use the synthesis report), but
uses more devices. For example, one of my programs written as VHDL
code produces
8 slices
10 flip flops
11 LUTs
9 IOBs
2 GCLKs
The minumum period is 3.991 ns (250 MHz)

When the same device was written with the schematic program it
produced
8 slices
8 flip flops
0 LUTs
10 IOBs
1 GCLK

but the minumum period is 5.979 ns (167 MHz)

In this example, notice that the VHDL design ended up with two clocks,
while the schematic design has only one. This makes me doubt that the
two designs are entirely equivalent. What's more, since the former
design has several clocks, one clock's minimum period alone doesn't
provide a metric for how fast it is, and it isn't comparable with the
latter design's clock period.

In other words, rewrite your VHDL code so that it is completely
synchronous and make sure it's behaviourally equivalent to the
schematics design. My guess is that the VHDL code will be slower then.
Has anyone done any research into why hand written VHDL is faster but
uses more devices? I am really interested in why my VHDL code is
faster than the schematic code. Any information that anyone can give
me would be great

I don't think one can make a general statement. It all depends on at
what level you're coding, on the application, and on how well you master
the language. Theoretically, you can acheive the optimal performance and
device utilization using both VHDL and schematics at structural level,
where you basically just connect the primitive elements of the circuit.
In practice, however, no sane human would do that for a large real-world
design. When it comes to comparing VHDL and schematics at higher levels,
both have their advantages and drawbacks. For example, using VHDL at
register-transfer level (RTL), it's easy to be lazy and create a design
that doesn't very naturally fit the chip you're designing for, and this
would result in a less efficient implementation. On the other hand, VHDL
synthesis tools of today have impressive optimization algorithms that
will remove unnecessary elements and utilize the chip cleverly in ways
that you wouldn't think of when designing with schematics. You can find
more pro's and con's in most introductory books on VHDL.

Hope this helps!

/Jerker
 
Z

ZackS

Thanks for the response, very helpful. One more question. My knowledge of
VHDL programming is limited and I would like to know why the compiler
thinks that my asynchronous reset is a clock signal. Here is my code.
***********************************************************

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

entity end_col_ctr_vhdl is
Port ( clk : in std_logic;
reset : in std_logic;
pix_ctr : inout std_logic_vector(7 downto 0);
end_col : out std_logic);
end end_col_ctr_vhdl;

architecture Behavioral of end_col_ctr_vhdl is

begin
COUNT: process(clk,reset)
variable ce : std_logic := '1';
begin
if reset = '1' then
pix_ctr <= "00000000";
end_col <= '0';
ce := '1';
elsif clk'event and clk = '1' and ce = '1' then
pix_ctr <= pix_ctr + 1;
end if;

if pix_ctr = "11101111" then
end_col <= '1';
ce := '0';
end if;
end process COUNT;
end Behavioral;
 
J

Just an Illusion

Hi ZackS,

Your 'reset' is certainly see as a 'gate' (not clock) of a d-latch for
end_col and ce signals (variable).

In fact it is better if you have a (sequential) process to generate the
counter incrementation (counter with enable command).
And an other (combinatory) process to compute end_col.

You can use end_col has enable command (because ce =~ not end_col).

Becarefull, in your design you have one count more than require before
blocking situation.

I rewrite your process with variable to show you what you have write.

*************************************************************

COUNT: process(clk,reset)
variable ce : std_logic := '1';
variable pix_ctr_in : std_logic_vector(7 downto 0);
begin
pix_ctr_in := pix_ctr;
if reset = '1' then
pix_ctr_in <= "00000000";
end_col <= '0';
ce := '1';
elsif clk'event and clk = '1' and ce = '1' then
pix_ctr_in := pix_ctr_in + 1;

end if;
-- Front this point pix_ctr_in <> pix_ctr

if pix_ctr = "11101111" then
end_col <= '1';
ce := '0';
end if;
pix_ctr <= pix_ctr_in;
end process COUNT;

*************************************************************

JaI
 
J

Jerker Hammarberg \(DST\)

Thanks for the response, very helpful. One more question. My knowledge
of
VHDL programming is limited and I would like to know why the compiler
thinks that my asynchronous reset is a clock signal. Here is my code.

I think it has to do with that the switching of end_col and ce aren't
explicitly synchronized with clk, so the synthesis tool infers latches for
them instead of clocked flip-flops. Since the reset signal can trigger the
latches, the tool decides to use one of the clock nets for it.

I would recommend you to rewrite the process as follows:

COUNT: process(clk,reset)
variable ce : std_logic := '1';
begin
if reset = '1' then
pix_ctr <= "00000000";
end_col <= '0';
ce := '1';
elsif clk'event and clk = '1' then
if ce = '1' then
pix_ctr <= pix_ctr + 1;
end if;
if pix_ctr = "11101110" then
end_col <= '1';
ce := '0';
end if;
end if;
end process COUNT;

That way, the code adheres to the general template for synchronous processes
with asynchronous reset. Notice that I changed "11101111" in your code to
"11101110" here, because now that the compare is placed among the clocked
statements, it will be delayed one cycle. To put it another way, pix_ctr
will be increased from "11101110" to "11101111" at the same instant as when
end_col and ce are updated.

Another suspicious spot in your code is that pix_ctr is declared "inout".
Since this process drives pix_ctr all the time, noone else should drive it,
so I think it should be safe to declare it "out".

Notice that I'm not exactly an expert either, but I hope the real experts
will correct me if I'm wrong!

/Jerker
 
J

Just an Illusion

Hi Jerker,

You are right, as for inout, but perhaps the end of count is really
"11101111".

In that case it is better if process is like:

----\/--------------\/-----------------
use ieee.std_logic_arith.all;
....
signal pix_ctr_i : interger;
....

COUNT: process(clk,reset)
begin
if reset = '1' then
pix_ctr_i <= 0;
elsif clk'event and clk = '1' then
if end_col = '0' then
pix_ctr_i <= pix_ctr_i + 1;
end if;
end if;
end process COUNT;

pix_ctr <= conv_std_logic_vector(pix_ctr_i, 8);

end_col <= '1' when pix_ctr = 239 else '0';

----/\--------------/\----------------
By this code you no more require variable ce, and you don't need have a
ff for end_col.


JaI
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top