srohrer32
srohrer32

Reputation: 67

Errors with Counters in FPGA Resetting (using VHDL)

I am trying to make a design with multiple counters cycling from 0 to 109. However, the counters do not reset at 109, but rather 127 (their max value) when on the FPGA. They do work in simulation though. Below is my code:

speaker_processing_r : process(us_clock)
begin
    if(rising_edge(us_clock)) then   
        if(i_reset = '1') then
            output_counter_r_0 <= 0;
            output_counter_r_1 <= (sample_period);
            output_counter_r_2 <= (sample_period*2);
            output_counter_r_3 <= (sample_period*3);
            output_counter_r_4 <= (sample_period*4);    
            data_r_0           <= X"00";
            data_r_1           <= X"00";
            data_r_2           <= X"00";
            data_r_3           <= X"00";
            data_r_4           <= X"00";                                            

        else    

            --Output Conditions based on delays calculated or inserted
            if(output_counter_r_0 = 2) then
                data_r_0 <= shift_register_r(0);
            elsif(output_counter_r_0 = delay_1) then
                data_r_1 <= shift_register_r(0);
            elsif(output_counter_r_0 = delay_2) then
                data_r_2 <= shift_register_r(0); 
            elsif(output_counter_r_0 = delay_3) then
                data_r_3 <= shift_register_r(0);
            elsif(output_counter_r_0 = delay_4) then
                data_r_4 <= shift_register_r(0);
            elsif(output_counter_r_0 = (sample_period*5-1)) then
                output_counter_r_0    <= 0;
            end if;

            if(output_counter_r_1 = 2) then
                data_r_0 <= shift_register_r(1);
            elsif(output_counter_r_1 = delay_1) then
                data_r_1 <= shift_register_r(1);
            elsif(output_counter_r_1 = delay_2) then
                data_r_2 <= shift_register_r(1); 
            elsif(output_counter_r_1 = delay_3) then
                data_r_3 <= shift_register_r(1);
            elsif(output_counter_r_1 = delay_4) then
                data_r_4 <= shift_register_r(1);
            elsif(output_counter_r_1 = (sample_period*5-1)) then
                output_counter_r_1    <= 0;
            end if;

            if(output_counter_r_2 = 2) then
                data_r_0 <= shift_register_r(2);
            elsif(output_counter_r_2 = delay_1) then
                data_r_1 <= shift_register_r(2);
            elsif(output_counter_r_2 = delay_2) then
                data_r_2 <= shift_register_r(2); 
            elsif(output_counter_r_2 = delay_3) then
                data_r_3 <= shift_register_r(2);
            elsif(output_counter_r_2 = delay_4) then
                data_r_4 <= shift_register_r(2);
            elsif(output_counter_r_2 = (sample_period*5-1)) then
                output_counter_r_2    <= 0;
            end if;

            if(output_counter_r_3 = 2) then
                data_r_0 <= shift_register_r(3);
            elsif(output_counter_r_3 = delay_1) then
                data_r_1 <= shift_register_r(3);
            elsif(output_counter_r_3 = delay_2) then
                data_r_2 <= shift_register_r(3); 
            elsif(output_counter_r_3 = delay_3) then
                data_r_3 <= shift_register_r(3);
            elsif(output_counter_r_3 = delay_4) then
                data_r_4 <= shift_register_r(3);
            elsif(output_counter_r_3 = (sample_period*5-1)) then
                output_counter_r_3    <= 0;
            end if;

            if(output_counter_r_4 = 2) then
                data_r_0 <= shift_register_r(4);
            elsif(output_counter_r_4 = delay_1) then
                data_r_1 <= shift_register_r(4);
            elsif(output_counter_r_4 = delay_2) then
                data_r_2 <= shift_register_r(4); 
            elsif(output_counter_r_4 = delay_3) then
                data_r_3 <= shift_register_r(4);
            elsif(output_counter_r_4 = delay_4) then
                data_r_4 <= shift_register_r(4);
            elsif(output_counter_r_4 = (sample_period*5-1)) then
                output_counter_r_4    <= 0;
            end if;

            output_counter_r_0 <= output_counter_r_0 +1;
            output_counter_r_1 <= output_counter_r_1 +1;
            output_counter_r_2 <= output_counter_r_2 +1;
            output_counter_r_3 <= output_counter_r_3 +1;
            output_counter_r_4 <= output_counter_r_4 +1;

        end if;     
    end if;
end process;

All of the delay (delay_1, delay_2, delay_3, delay_4) signals are generics as well as sample_period. The period of us_clock is 1 microsecond. Any insight as to why they do not reset is appreciated.

Upvotes: 0

Views: 244

Answers (1)

fru1tbat
fru1tbat

Reputation: 1625

I see one obvious problem and one potential problem.

First, as you are assigning output_counter_r_* <= output_counter_r_* + 1 at the end of the process, these take precedence over the assignments within the if blocks (see How does signal assignment work in a process?). The counter signal assignment doesn't "take effect" until the process completes here, so anything before those increment statements will be ignored. I'm surprised it worked in sim, actually. What simulator are you using?

The second potential problem is that the rollover condition of the counter is contingent on none of the preceding if-conditions being true. Is this intentional? It shouldn't be an issue unless any delay_* happens to be equal to sample_period*5-1, but you may want to try splitting it as:

if(output_counter_r_0 = 2) then
  data_r_0 <= shift_register_r(0);
elsif(output_counter_r_0 = delay_1) then
  data_r_1 <= shift_register_r(0);
elsif(output_counter_r_0 = delay_2) then
  data_r_2 <= shift_register_r(0); 
elsif(output_counter_r_0 = delay_3) then
  data_r_3 <= shift_register_r(0);
elsif(output_counter_r_0 = delay_4) then
  data_r_4 <= shift_register_r(0);
end if;

if(output_counter_r_0 = (sample_period*5-1)) then
  output_counter_r_0    <= 0;
else
  output_counter_r_0 <= output_counter_r_0 +1;
end if;

(Unless that's not the function you intended.)

Edit for further explanation

Basically, in a process in VHDL, signals are only assigned when the process suspends/waits (i.e., for normal processes, at the end), which means that only the last assignment to the signal is used. This is useful for several reasons that I won't get into here, but the result is that since you're always incrementing the counters at the end of the process, anything else you've done to them earlier in the process will be ignored. You can code it the way I've shown above, unless it was intentional that your rollover condition was dependent on the other counter comparisons - "if = 2, do this, otherwise if = delay_1 do this, ... otherwise if it's at the limit, roll it over." With that logic, the counter will only roll over if none of the other conditions is true.

If this was intentional, the easiest solution would just be to move the increments to the beginning of the process, so they would be overridden by the rollover checks. An alternate (perhaps safer?) solution would be modifying the second if block above to explicitly check for exactly what conditions you want. Up to you.

Upvotes: 2

Related Questions