FPGA: using both falling and rising edges in the same process

I am new to fpga and vhdl ..

My development environment looks like this.

FPGA: Spartan 6 XC6SLX9

Compiler: ISE 14.04

Simulator: Isim

I am making a simple counter, but there are some things that I cannot figure out.

The following code is what I wrote. I expected w_count to increment every falling edge of the clock and reset to 0 when w_count reaches N_data during the rising edge of the clock. There were no problems during compilation and the simulation works as well as I expected. But when applied to a real fpga, w_count was incremented for every trigger, but when N_data was reached, it was not initialized to zero.

w_state_proc : process(r_clk, reset_n_clean)
begin
    if(reset_n_clean = '0') then
        w_count <= 0;
    elsif(r_clk'event and r_clk = '0') then
        if(state = write_state and w_proc = '1') then
            w_count <= w_count + 1;
        end if;
    elsif(r_clk'event and r_clk = '1') then
        if(w_count = N_data) then
            w_count <= 0;
        end if;
    end if;
end process w_state_proc;

      

When I changed the position of the two elsif statements, the w_count didn't increase at all.

w_state_proc : process(r_clk, reset_n_clean)
begin
    if(reset_n_clean = '0') then
        w_count <= 0;
    elsif(r_clk'event and r_clk = '1') then
        if(w_count = N_data) then
            w_count <= 0;
        end if;
    elsif(r_clk'event and r_clk = '0') then
        if(state = write_state and w_proc = '1') then
            w_count <= w_count + 1;
        end if;
    end if;
end process w_state_proc;

      

I could see a lot of feedback that these statements are deprecated, but I don't understand why these statements are causing these problems ..

+3


source to share


1 answer


There is no double data rate (DDR) flip flop in FPGA in common fabric, so it is not recommended - "as is", it cannot implement the desired functionality.

Also, you are using an asynchronous reset. While this is possible, it is also highly discouraged as the FPGA already has synchronous reset flip flops and so unlike an ASIC no additional logic is required and you will get a known value for each signal even without a reset. An asynchronous reset will create problems for you by creating sync in one way or another.

In your example, there is no need for DDR FF anyway. It would seem the reason to have your behavior is that w_count can be cleared between clock cycles so that w_count is never N_data when incremented. Why not compare it to less than one?



Or you can use variables (very carefully!) To achieve very similar behavior:

  w_state_proc : process(r_clk) is
    variable v_count : integer range 0 to N_data;
  begin
    if (rising_edge(r_clk)) then
      v_count := w_count;
      if(state = write_state and w_proc = '1') then
        v_count := v_count + 1;
      end if;

      if(reset_n_clean = '0' or v_count = N_data) then
        w_count <= 0;
      else
        w_count <= v_count;
      end if;

    end if;
  end process w_state_proc;

      

If you really need w_count to be N_data for half a clock cycle, you can always do the tactic twice as fast and use the enable signal in effect every other clock cycle and propagate it along with the pipeline. This will give you a whole host of other (very educational) challenges, but doable.

+3


source







All Articles