I'm a fpga & vhdl newbie..
My development environment is as follows.
FPGA :Spartan 6 XC6SLX9
Compiler : ISE 14.04
Simulator : Isim
I'm making a simple counter, but there are some things I can't understand.
The following code is what I wrote. What I expected was w_count
increased every falling edge of the clock, and reset to 0 when w_count
reach to N_data
during rising edge of the clock. There was no problem in the compilation process, and simulation also works well as I expected. But when applied to real fpga, w_count
was incremented for each trigger, but was not initialized to zero when reached to N_data
..
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 two elsif
statements, 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 not recommended, but I don't understand why these statements cause this problems..
Your FPGA doesn't have dual data rate (DDR) flip flops in the general purpose fabric, that's why it's not recommended - "as is" it cannot implement the desired functionality.
Also, you are using asynchronous reset. While possible, also highly not recommended, as the FPGA already has synchronous reset flip-flops and thus it doesn't take any extra logic have it, unlike in ASIC, and you'll get known value to every signal even without reset. Asynchronous reset will create trouble for you in achieving the timing closure one way or another.
In your example, there is really no need for DDR FFs anyhow. It would seem that the reason to have the behavior you have is that the w_count can be cleared between the clock cycles so that w_count never is N_data when incremented. Why not have the compare it to value that is one smaller?
Or, you could 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 would really need the w_count to have the value of N_data for half a clock cycle, you can always make the clock twice as fast and use enable signal active every other clock cycle, and propagate that alongside your pipeline. That'll get you in a whole host of other (very educational) trouble, but doable.