FPGARelated.com
Forums

Xst optimizes almost everything away

Started by Adrian Knoth November 22, 2005
Hi,

this is my first real VHDL project, so it's perhaps more a
beginner's question than a problem with Xst.

I have some components for my module two_pc, but when I
translate it in ISE, both "translate" and "Place&Route"
have warnings (system report says 308 warnings).

The problem: xst claims that some signals are connected
but never used. For one component it even says there
isn't any connection:

Xst:524 - All outputs of the instance <bild> of the block
          <bildspeicher> are unconnected in block <two_pc>.

I don't think that's true:

      bild : bildspeicher
      port map (reset => reset,
                                         clk => clk_i,
                                         addra => bildaddr1,
                                         addrb => bildaddr2,
                                         DOA => bilddaten1,
                                         DOB => bilddaten2
       );


(DOA and DOB are outputs) and there is a process using them:

   chooser : process (clk_i, reset) --, update_input)
           variable links,rechts : std_logic_vector (31 downto 0);
        begin
           if (reset='1') then
              input <= (others => '0');
           elsif (clk_i'event and clk_i='1') then
              if (update_input'event and update_input='1') then
                  rechts := bilddaten1;
                  case spalte is
                         when "00" =>                            
                            input (31) <= '0';
                            input (30 downto 24) <= rechts (31 downto 25);
                            input (23 downto 16) <= rechts (26 downto 19);
                            input (15 downto 08) <= rechts (20 downto 13);
                            input (07 downto 00) <= rechts (14 downto 07);
                       when "01" =>
                            bildaddr2 (1 downto 0) <= "00";
                            links := bilddaten2;
                            input (31 downto 24) <= links (8 downto 1);
                            input (23 downto 21) <= links (2 downto 0);
                            input (20 downto 16) <= bilddaten1 (31 downto 27);
                            input (15 downto 08) <= bilddaten1 (28 downto 21);
                            input (7 downto 0)  <= bilddaten1 (22 downto 15);
                       when "10" =>
                            bildaddr2 (1 downto 0) <= "01";
                            links := bilddaten2;
                            input (31 downto 24) <= links (16 downto 9);
                            input (23 downto 16) <= links (10 downto 3);
                            input (15 downto 11) <= links ( 4 downto 0);
                            input (10 downto  8) <= bilddaten1 (31 downto 29);
                            input ( 7 downto  0) <= bilddaten1 (30 downto 23);
                        when "11" =>
                            bildaddr2 (1 downto 0) <= "10";
                            links := bilddaten2;
                            input (31 downto 24) <= links (24 downto 17);
                            input (23 downto 16) <= links (18 downto 11);
                            input (15 downto  8) <= links (12 downto  5);
                            input (7 downto 1)  <= links (6 downto 0);
                            input (0  downto 0)   <= bilddaten1 (31 downto 31);
                       when others => input <= (others => '0');
                    end case;
                 end if;
                end if;
        end process chooser;

There are more of such "warnings":

Xst:1291 - FF/Latch <outbuf_D_7> is unconnected in block <two_pc>.

(and _D_6 .. -D_0, 8bit-std-logic-vector)

but I have:

   output_ff : process (clk_i, reset)
        begin
           if (reset='1') then
                        outbuf_A <= (others => '0');
                        outbuf_B <= (others => '0');
                        outbuf_C <= (others => '0');
                        outbuf_D <= (others => '0');
                elsif (clk_i'event and clk_i='1') then
                   if (write_A = '1') then
                          outbuf_A <= output_A;
                          outbuf_B <= output_B;
                          outbuf_C <= output_C;
                          outbuf_D <= output_D;
                        end if;
                end if;
        end process output_ff;

and

        output (31 downto 24) <= outbuf_A (7 downto 0);
        output (23 downto 16) <= outbuf_B (7 downto 0);
        output (15 downto 8) <= outbuf_C (7 downto 0);
        output (7 downto 0) <= outbuf_D (7 downto 0);

Xst: FF/Latch  <inbuf_A_6> (without init value) has a constant value of 0 
     in block <two_pc>.

   input_ff : process (clk_i, reset)
        begin
           if (reset='1') then
                        inbuf_A <= (others => '0');
                        inbuf_B <= (others => '0');
                        inbuf_C <= (others => '0');
                        inbuf_D <= (others => '0');
           elsif (clk_i'event and clk_i='1') then
               if (read_A = '1') then
                        inbuf_A <= input (31 downto 24);
                        inbuf_B <= input (23 downto 16);
                        inbuf_C <= input (15 downto 8);
                        inbuf_D <= input (7 downto 0);
                  end if;
                end if;
        end process input_ff;


(input itself is assigned by the chooser-process).

All my important logic gets optimized away ;) What's the
problem? All signals in question (for which Xst claims
they are never assigned) are assigned by processes.

TIA

-- 
mail: adi@thur.de  	http://adi.thur.de	PGP: v2-key via keyserver

Geld allein macht nicht gl&#4294967295;cklich - es mu&#4294967295; dir auch geh&#4294967295;ren
Adrian Knoth wrote:
> this is my first real VHDL project, so it's perhaps more a > beginner's question than a problem with Xst. > > I have some components for my module two_pc, but when I > translate it in ISE, both "translate" and "Place&Route" > have warnings (system report says 308 warnings). > > The problem: xst claims that some signals are connected > but never used. For one component it even says there > isn't any connection: > > Xst:524 - All outputs of the instance <bild> of the block > <bildspeicher> are unconnected in block <two_pc>. > > I don't think that's true:
> chooser : process (clk_i, reset) --, update_input) > variable links,rechts : std_logic_vector (31 downto 0); > begin > if (reset='1') then > input <= (others => '0'); > elsif (clk_i'event and clk_i='1') then > if (update_input'event and update_input='1') then
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This statement completely confuses the synthesizer. I assume you wish to look for the edge of update_input? You can't do it this way. You'll need to use a delay flip-flop (clocked by clk) and then test the state of both update_input and update_input_delayed. If update_input is true and update_input_delayed is false, then you've got the edge of update_input. -a
Yo Adrian,

(I assume that it's not something simple, like the signals not making
it to an output pin on the device)

Take a close look at the beginning of your 'chooser' process:

  chooser : process (clk_i, reset) --, update_input)
           variable links,rechts : std_logic_vector (31 downto 0);
        begin
           if (reset='1') then
              input <= (others => '0');
           elsif (clk_i'event and clk_i='1') then
              if (update_input'event and update_input='1') then
                  rechts := bilddaten1;

The elsif predicate is a normal enough rising edge clock condition on
"clk_i". But then it is followed by an if predicate that indicates a
rising edge clock condition on "update_input". What you've coded is a
detector that looks for simultaneous rising edges, and this is not
realistic for synthesis (not realistic period, the two signals come in
on separate pins, and as Einstein observed, there is no simultaneity
for separated points. I suspect you had to use the "--, update_input)"
in the sensitivity list in order to get the simulation to work, but the
synthesis tool complained so you commented it out. Well, keep it out,
but change your if statement to read:
             if update_input='1' then
which is the standard construction for a clock enable.

HTH,
John

Andy Peters <Bassman59a@yahoo.com> wrote:

>> chooser : process (clk_i, reset) --, update_input) >> variable links,rechts : std_logic_vector (31 downto 0); >> begin >> if (reset='1') then >> input <= (others => '0'); >> elsif (clk_i'event and clk_i='1') then >> if (update_input'event and update_input='1') then > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > I assume you wish to look for the edge of update_input? You can't do
Yes.
> it this way. You'll need to use a delay flip-flop (clocked by clk) and > then test the state of both update_input and update_input_delayed. If > update_input is true and update_input_delayed is false, then you've got > the edge of update_input.
Wouldn't rising_edge (update_input) do the job? Or falling_edge (), if I need to know whether a signal was once set and is now off (write_A indicates that my processor core has written its result and I now can use the value of the output-FFs to write it to vga.) How do I synchronize these processes in VHDL? I have the output-FFs containing the current value and need to bitwise store the content in the VGA-RAM every time my write_A indicates that there are new data. I currently use a process for this but I don't know if it really stops after executing the for-loops, how many clock cycles are used for each loop iteration, if every statement in the loop-body is executed in one clock cycle and so on: to_video : process (clk_i, reset) variable tmp_vga : std_logic_vector (31 downto 0); begin if (reset='1') then addr_vga <= (others => '0'); web_i <= '0'; elsif (falling_edge (write_A)) then tmp_vga := output; for j in 3 downto 0 loop for i in 6 downto 1 loop web_i <= '1'; dib_i (0 downto 0) <= tmp_vga (j * 8 + i downto j * 8 + i); web_i <= '0'; addr_vga <= addr_vga + 1; end loop; end loop; end if; end process to_video; (web_i enables the vga input, addr_vga should be the bitaddress in the VGA RAM) Let's say write_A goes up for two cycles every 24 clocks (assumption, I don't know the real amount of clocks between these two pulses), indicating that there is now new information available at the output (output is DFF-buffered (but currently optimized away ;)). Does the process above would poke the selected bits to dib_i or do I have to keep track of write_A by something like a state machine? -- mail: adi@thur.de http://adi.thur.de PGP: v2-key via keyserver Internet nach 1996 ist ohnehin nur noch verkommerzialisierte Schei&#4294967295;e (Christian Anger)
JustJohn <john.l.smith@titan.com> wrote:

> (I assume that it's not something simple, like the signals not making > it to an output pin on the device)
I think so, too.
> elsif (clk_i'event and clk_i='1') then > if (update_input'event and update_input='1') then > rechts := bilddaten1; >
> for separated points. I suspect you had to use the "--, update_input)" > in the sensitivity list in order to get the simulation to work, but the > synthesis tool complained so you commented it out. Well, keep it out, > but change your if statement to read: > if update_input='1' then > which is the standard construction for a clock enable.
Thanks, this sounds reasonable to me. Unfortunately it doesn't change a thing ;) I also removed some other statements of this kind. Perhaps the problem is in the generation of update_input? I have to wait with new input until the core has read it, so I have a read_A going from 0 to 1 for two cycles if the data was captured: addrgen : process (clk_i, reset) -- , read_A) begin if (reset='1') then zeile <= "0000000"; spalte <= "00"; elsif (clk_i'event and clk_i='1') then for i in 0 to 3 loop spalte <= spalte + 1; for j in 0 to 127 loop zeile <= zeile + 1; -- wait for core to read input update_input <= '1'; while (read_A = '0') loop null; -- read_A is low until core has captured data end loop; update_input <= '0'; end loop; reset_trig <= '1'; reset_trig <= '0'; end loop; end if; end process addrgen; I think the while-loop is more or less stupid, all I want to do is to wait for read_A going up and down, indicating that the new input data was captured by the processing core. -- mail: adi@thur.de http://adi.thur.de PGP: v2-key via keyserver Lieber Erstattung als Bestattung
Adrian Knoth wrote:

> Wouldn't rising_edge (update_input) do the job? Or falling_edge (), > if I need to know whether a signal was once set and is now off
Not for synthesis. Here is a similar example with just one clock. http://home.comcast.net/~mike_treseler/rise_count.vhd Note the synthesis template at the end of the file. -- Mike Treseler
Adrian Knoth wrote:
> Andy Peters <Bassman59a@yahoo.com> wrote: > > >> chooser : process (clk_i, reset) --, update_input) > >> variable links,rechts : std_logic_vector (31 downto 0); > >> begin > >> if (reset='1') then > >> input <= (others => '0'); > >> elsif (clk_i'event and clk_i='1') then > >> if (update_input'event and update_input='1') then > > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > > > I assume you wish to look for the edge of update_input? You can't do > > Yes. > > > it this way. You'll need to use a delay flip-flop (clocked by clk) and > > then test the state of both update_input and update_input_delayed. If > > update_input is true and update_input_delayed is false, then you've got > > the edge of update_input. > > Wouldn't rising_edge (update_input) do the job? Or falling_edge (), > if I need to know whether a signal was once set and is now off > (write_A indicates that my processor core has written its result > and I now can use the value of the output-FFs to write it to > vga.)
THINK HARDWARE. How would you implement the rising_edge() function? How does the hardware "know" when an edge occurs? Here's a point you must understand: the process statement myflop : process (clk, rst) is begin if (rst = '1') then q <= '0'; elsif rising_edge(clk) then q <= d; end if; end process myflop; follows a template that the synthesis tool uses to generate hardware. The synthesis tool tries to match the code against standard templates to infer various hardware structures (flip-flops, RAMs, etc). (It also works to minimize logic, etc.) The notation above conveniently describes a clearable D flip-flop. On the rising edge of clk, it looks at the D input and assigns it to the Q output. You can't use the rising_edge() function in the way you describe ... there is no hardware equivalent..
> How do I synchronize these processes in VHDL? I have the output-FFs > containing the current value and need to bitwise store the content > in the VGA-RAM every time my write_A indicates that there are new > data. I currently use a process for this but I don't know if it > really stops after executing the for-loops, how many clock cycles > are used for each loop iteration, if every statement in the > loop-body is executed in one clock cycle and so on: > > to_video : process (clk_i, reset) > variable tmp_vga : std_logic_vector (31 downto 0); > begin > if (reset='1') then > addr_vga <= (others => '0'); > web_i <= '0'; > elsif (falling_edge (write_A)) then
This is another problem. Your sensitivity list includes a clock and a reset (which is correct), but your code tells us that you want write_A to be the clock used by the flip-flops. Your synthesis tool should barf on this.
> tmp_vga := output; > for j in 3 downto 0 loop > for i in 6 downto 1 loop > web_i <= '1'; > dib_i (0 downto 0) <= tmp_vga (j * 8 + i downto j * 8 + i); > web_i <= '0'; > addr_vga <= addr_vga + 1; > end loop; > end loop; > end if; > end process to_video; > > (web_i enables the vga input, addr_vga should be the bitaddress in > the VGA RAM) > > Let's say write_A goes up for two cycles every 24 clocks (assumption, > I don't know the real amount of clocks between these two pulses), > indicating that there is now new information available at the > output (output is DFF-buffered (but currently optimized away ;)). > > Does the process above would poke the selected bits to dib_i or > do I have to keep track of write_A by something like a state machine?
Assuming write_A is synchronous to your clock, you have a couple of options. If your data remain valid during the time write_A is asserted, you can use write_A directly as a clock enable: myenabledflop : process (clk, rst) is begin if (rst = '1') then q <= '0'; elsif rising_edge(clk) then if (write_A = '1') then q <= d; end if; end if; end process myenabledflop; If you really do need to do your work on the rising edge of write_A, then you code an edge detector and use that as your clock enable: myedgedetectflop : process (clk, rst) is begin if (rst = '1') then write_A_d <= '0'; q <= '0'; elsif rising_edge(clk) then write_A_d <= write_A; -- delay for edge detect if (write_A = '1' and write_A_d = '0') then q <= d; end if; end if; end process myedgedetectflop; Is this clear? -a
Hi Adrian,

You wrote:

>addrgen : process (clk_i, reset) -- , read_A) >begin > if (reset='1') then > zeile <= "0000000"; > spalte <= "00"; > elsif (clk_i'event and clk_i='1') then > for i in 0 to 3 loop > spalte <= spalte + 1; > for j in 0 to 127 loop > zeile <= zeile + 1; > -- wait for core to read input > update_input <= '1'; > while (read_A = '0') loop > null; -- read_A is low until core has captured data > end loop; > update_input <= '0'; > end loop; > reset_trig <= '1'; > reset_trig <= '0'; > end loop; > end if; >end process addrgen;
There is a lot wrong here, and I can't teach you all about H/W design vs. S/W coding, but will try to touch on some key points. I had a look at your website, and see that you have experience with Ada. Do not be fooled by any outward similarities between Ada and VHDL. There are many differences, some obvious and some very subtle. There is a lot more going on 'behind the curtain' in VHDL. Code written in Ada is has a single primary destination; it is compiled into an object file containg bits that control a processor's execution. Code written in VHDL has two primary destinations; it is compiled by a simulator to produce bits (dependency tables, signal lists, and a whole lot more) to control a simulator's exection, and it is compiled by a synthesizer to produce a netlist that is eventually transformed into bits to control the FPGA configuration. Code written for a processor vs. VHDL code: On a processor, statements execute sequentially, and some kind of timing is almost always imposed on their execution by the processor's clock. In VHDL, all statements outside of a process execute concurrently, with _no_ timing. Statements inside a process execute sequentially, but there is still _no_ timing, everything 'happens in an instant', with the exception of 'wait' statements, which cause suspension of process statement execution until the wait condition is satisfied. BUT 'wait' statements are absolutely verboten in synthesizable VHDL. (Wait statements are used in testbench code, and others can tell you all about the importance of testbenches, and the differences between them and synthesizable code) In a program running on a processor, you can write as part of a function or procedure: reset_trig <= '1'; reset_trig <= '0'; and when that function/procedure is called, reset_trig will go to 1 for some number of processor clock ticks, and then go to 0. In a VHDL process, even though the statements execute sequentially, there is nothing to give any duration to the 1 value. If it were to be synthesized, this might generate a Dirac delta function, or maybe a glitch, but the first is a theoretical construct, and the second is really nasty, so this does not produce anything usable. 'For' and 'while' loops: For loops are typically used to iterate over vector indices, where the iterator is used for selection purposes. Abreviating your code, you've written: addrgen : process (clk_i, reset) begin if (reset='1') then ... elsif (clk_i'event and clk_i='1') then for i in 0 to 3 loop spalte <= spalte + 1; ... end loop; end if; end process addrgen; The iterator 'i' is not even used inside the loop, which should be a tip-off that something is not right. Think about what this might do, even if it were a valid piece of code: Every time a clock edge occurs, "in an instant" the 'for' loop is executed, and when the process exits, the value of spalte has been incremented 4 times. This would mean that every clock edge would increment spalte by 4. HOWEVER, this is NOT valid code, and both simulation and synthesis produce a counter that increments by 1 on each clock edge. (Should the tools not even allow this to compile? I don't know, but mine do) All the problems here stem from a common source, thinking that a H/W process is like a S/W procedure or function, but it is not. Concentrate on the basic way process works in synthesizable code: Whenever an event occurs on a member of the sensitivity list, the process is entered, statements run 'in an instant', and the process exits. It may take days, weeks, or even months before it feels natural. You seem like a smart cookie, it shouldn't take too long, keep at it. It might be easier if VHDL had a different word for process, like 'eventblock' or some such, to stress the difference. Adrian, you've got a bit more learning curve to climb, I've got to get back to work, and don't want to write your code for you. The last I can advise is look at other good code examples, get another book, and keep at it. Regards, John
OOOPS,
I wrote:
>addrgen : process (clk_i, reset) >begin > if (reset='1') then > ... > elsif (clk_i'event and clk_i='1') then > for i in 0 to 3 loop > spalte <= spalte + 1; > ... > end loop; > end if; >end process addrgen; > > >The iterator 'i' is not even used inside the loop, which should be a >tip-off that something is not right. >Think about what this might do, even if it were a valid piece of code: >Every time a clock edge occurs, "in an instant" the 'for' loop is >executed, and when the process exits, the value of spalte has been >incremented 4 times. This would mean that every clock edge would >increment spalte by 4. HOWEVER, this is NOT valid code, and both >simulation and synthesis produce a counter that increments by 1 on each >clock edge. (Should the tools not even allow this to compile? I don't >know, but mine do)
I said that wrong, it IS VALID CODE, but silly. It is equivalent to writing: spalte <= spalte + 1; spalte <= spalte + 1; spalte <= spalte + 1; spalte <= spalte + 1; but the net result is that spalte only gets updated to spalte + 1 when the process exits. It doesn't matter how many assignments you make to a _signal_ during a process 'instant', only the very last assignment is performed when the process exits (mix 'wait's into it, and things are different, but remember, no waits allowed in synthesizable code). Variables (instead of signals) are more intuitive to the programming mindset, see Mike's templates. See, I've been using VHDL for only 4 years now, and still stumble occasionally. Regards, John
Andy Peters <Bassman59a@yahoo.com> wrote:

> THINK HARDWARE.
Thanks, this was more or less the main reason.
> How would you implement the rising_edge() function? How does the > hardware "know" when an edge occurs?
Thanks for this explanation, I ever wondered how to do this, your code has enlightened me.
> follows a template that the synthesis tool uses to generate hardware. > The synthesis tool tries to match the code against standard templates > to infer various hardware structures (flip-flops, RAMs, etc). (It also > works to minimize logic, etc.)
I was misled by a statement in mind "With VHDL you can design your hardware if it was software." Unfortunately the quote originally said "With SystemC ..." and I bet is as wrong as my version ;)
> Is this clear?
Yes. I have everything in my bitstream now. Thanks for your help (and to all others, too). -- mail: adi@thur.de http://adi.thur.de PGP: v2-key via keyserver For more information see readme-file WASN.DAT