Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Unexpected values in the fibonnaci while doing FSMD Design

Status
Not open for further replies.

ChrisRR

Newbie level 6
Joined
Aug 8, 2009
Messages
11
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,393
FSMD Design

I have been learning how to write VHDL using the book "FPGA prototyping by VHDL examples: Xilinx Spartan-3 version" and I'm working through the FSMD design examples and loading testbench vectors from external files and writing the output data to text files to quickly view without having to check the waveforms.

But in my output I was getting some unexpected values in the fibonnaci example. Here's the waveform. **broken link removed**

So when I put the value 08 into the component I expected to get the output 15 (hex) but instead get FFFFF. I see from the waveform that when I sample right on the rising edge of done_tick the data output is changing from 15 to FFFFF. Is this FFFFF output just a product of the simulator and it would run correctly in synthesis or would the clock propogation cause the value to still be FFFFF in synthesis?

If you need to see the code I can post it here but the book is also available on Google Books, starting page 140

Thanks
 

FSMD Design

the FFFFFF value is likely a feature of the code, not specificially simulation. You cannot get that book on google books for free, so I cannot see all of the code. But the answer is it will probably do the same on hardware.

If you have any further questions - ask away.
 

Re: FSMD Design

I presume it's not an issue to post their code here
Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity fib is
  port(
    clk, reset: in std_logic;
    start: in std_logic;
    i: in std_logic_vector(4 downto 0);
    ready, done_tick: out std_logic;
    f: out std_logic_vector(19 downto 0)
  );
end fib;

architecture arch of fib is
  type state_type is (idle, op, done);
  signal state_reg, state_next: state_type;
  signal t0_reg, t0_next: unsigned(19 downto 0);
  signal t1_reg, t1_next: unsigned(19 downto 0);
  signal n_reg, n_next: unsigned(4 downto 0);
begin
  process(clk, reset)
  begin
    if reset='1' then
      state_reg <= idle;
      t0_reg <= (others => '0');
      t1_reg <= (others => '1');
      n_reg <= (others => '0');
    elsif (clk'event and clk='1') then
      state_reg <= state_next;
      t0_reg <= t0_next;
      t1_reg <= t1_next;
      n_reg <= n_next;
    end if;
  end process;

  process(state_reg, n_reg, t0_reg, t1_reg, start, i, n_next)
  begin
    ready<='0';
    done_tick <= '0';
    state_next <= state_reg;
    t0_next <= (others => '0');
    t1_next <= (others => '1');
    n_next <= n_reg;
    case state_reg is
      when idle =>
	ready <= '1';
	if start='1' then
	  t0_next <= (others => '0');
	  t1_next <= (0 => '1', others=>'0');
	  n_next <= unsigned(i);
	  state_next <= op;
	end if;
      when op =>
	if n_reg=0 then
	  t1_next<=(others=>'0');
	  state_next<=done;
	elsif n_reg=1 then
	  state_next <= done;
	else
	  t1_next<= t1_reg + t0_reg;
	  t0_next<= t1_reg;
	  n_next<= n_reg-1;
	end if;
      when done =>
	done_tick <= '1';
	state_next <= idle;
    end case;
  end process;

  f <= std_logic_vector(t1_reg);
end arch;

As you can see the output f is automatically assigned to t1_reg. In the FSM it sets a default value for t1_next to FFFFF so that on the rising edge as the FSM switches into the done state t1_reg gets assigned that value if no value is specified.
It seems to me that there needs to be a statement after "elsif n_reg=1 then" to preserve the value of t1_next but I didn't know if this was incorrect design as I took this exactly from how it's written in the book.

Added after 23 minutes:

For example here, I've changed the code so that the data is held for another clock cycle.

Code:
when op =>
	if n_reg=0 then
	  t1_next<=(others=>'0');
	  state_next<=done;
	elsif n_reg=1 then
	  t1_next <= t1_reg;
	  state_next <= done;

But I don't know why they didn't do that in the book. I don't know if I'm wrong because I don't actually know anything about FSMD design! Or if they made an error in their code.
 

FSMD Design

As an example of a 2 process state machine design, I think it serves it's purpose. Only now-adays, 2 process state machines are falling out of favour for the more compact and much more readable 1 process state machines.

With 1 process you never have to worry about creating tranparent latches from forgetting to set some output signal, and you dont have to worry about what signals are in the sensitivity list. I highly recommend you give the 1 process state machine a try (here is a recent example from one of my recent projects. There are no outputs other than the state, but you could add counters and other stuff in there):

Code:
process(clk, reset)
begin
  if reset = '1' then
    edge_state <= top_left;
    
  elsif rising_edge(clk) then
    
    case edge_state is
      
      when top_left => 
        edge_state        <= top_edge;
        
      ------------------------------------------  
      ------------------------------------------  
      
      when top_edge =>
        if filter_pos = END_OF_LINE then
          edge_state      <= left_edge;
        end if;
      
      ------------------------------------------  
      ------------------------------------------  
          
      when left_edge =>
        edge_state        <= centre;
        
      ------------------------------------------  
      ------------------------------------------  
        
      when centre =>
        if filter_pos = END_OF_LINE then
          if flush_stage then
            edge_state      <= bottom_left;  --because the input has finished, the current position will now restart
          else
            edge_state      <= left_edge;
          end if;
        end if;
          
      ------------------------------------------  
      ------------------------------------------  
      
      when bottom_left =>
        edge_state          <= bottom_edge;
        
      ------------------------------------------  
      ------------------------------------------    
      
      when bottom_edge => 
        if filter_pos = END_OF_AREA then
          edge_state        <= top_left;    --restart back to the beginning
        end if;
          
    end case;
  end if;
end process;
 

FSMD Design

For some of the examples it does offer example in both 2 process and 1 process state machines but sticks with 2 process for some reason. The only advantage it give for a 2 process design is that there are certain times where the synthesiser may create a more complex design due to the way the 1 process FSM is written.

I find the one process FSM much more readable but that might be because it looks more like the code I'm used to writing in game programming.
 

FSMD Design

Some old synthesisors only accepted 2 process state machines, and didnt like 1 process ones. Also, if there is any overhead with a 1 process state machine, it is tiny compared to the size of modern devices. Synthesisors are also constantly developing and the only advantage listed in that book has probably dissapeared as they have evolved.

top tip - write code to be meaningful and easy to understand. let the compiler do all the hard work!
 

FSMD Design

So back to my original point! Is making that change to the FSM to hold onto the data for another clock pulse incorrect or should that all function fine with it in there?
 

FSMD Design

The change you made should hold on to the value fine.
 

FSMD Design

the code for a 2 process state machine is a popular model in academia. It actually does offer up some advantages. (for example, you can write code like "if current state = x and next_state = y") But I've seen a lot of actual engineers use the 1 process version.

you also have people who seperate the SM from non-SM logic.


on the original question -- what do you want or expect. there are many different ways this is handled in practice. for example, the "last" output might be flagged as such. But maybe a "done" or "ready" is used to indicate the current output isn't valid new data.

in VHDL you can define the interfaces between your own modules. Unfortunantly, each person will make a different choice for the same word. "Ready", for example, might be used to indicate the system is ready for new inputs. Xilinx often uses it to indicate the output of the system is "ready".
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top