Jump to content
  • 0

Clock capabilities on Zybo and running two simultaneous sensitive counters in one IP


Ahmet

Question

For the past 3 weeks i have been fiddling around a bit with zybo even though i have just found out about what an fpga is using vivado i have made some simple  projects like a full adder using vhdl source code and hardware manager, an AXI IP block that can output PWM for given DUTY and Frequency/Period input.
But now i have hit a stand still in my new IP design, i need two counters that run simultaneously one will be a clock running at 50Mhz and the other will be catching the input signal the block gets and counting it.
My main problem is if i put both counters in the same process are they still as sensitive, and if they are not how can i trigger the other counter without getting a Multi-driven net error when one reaches the limit i want if they aren't in the same process(like one counter counts as a clock and gives me the info about the other clock in 10 ms intervals, in a way an encoder would.)

Link to comment
Share on other sites

7 answers to this question

Recommended Posts

@Ahmet,

Your problem is that you are attempting to use the rising edge of the incoming information.  The only rising edge your logic should depend upon is the rising edge of the clock.  Everything should depend upon that rising edge, and no other rising edges.

Now, given that advice, how to handle the encoder counts you are looking into?  It'll take a couple of steps.

Step one is to synchronize your input_bit with your system clock.  This (mostly) avoids any metastability issues:

always @(posedge S_AXI_ACLK)
  nearly_synched_input_bit <= input_bit;
always @(posedge S_AXI_ACLK)
  synched_input_bit <= nearly_synched_input_bit;

Step two is to detect rising edges in this synch'ed bit:

always @(posedge S_AXI_ACLK)
  last_input <= synched_input_bit;
always @(posedge S_AXI_ACLK)
  if ((synched_input_bit)&&(!last_input))
    counter <= counter + 1'b1;

Your separate timer can fit into it's own always block (Verilog term, VHDL term would be a process):

always @(posedge S_AXI_ACLK)
	if (timer >= 32'd100_000_000)
	begin
		timer_stb <= 1'b1;
		timer <= 0;
	end else begin
		timer <= timer + 1'b1;
		timer_stb <= 0;
	end

always @(posedge S_AXI_ACLK)
    if (timer_stb)
    	counted_teeth <= counter;

You can even adjust the original counter to clear itself anytime the timer has rolled over.  This would replace the always block (VHDL process) defining the counter, since only one always block can ever set the values of any register:

always @(posedge S_AXI_ACLK)
	if (timer_stb)
		counter <= 0;
	else if ((!last_input)&&(synched_input_bit)) // Count only positive transitions
		counter <= counter + 1'b1;

Is that closer to what you are trying to do?

Dan

Link to comment
Share on other sites

@Ahmet,

Much as I try, I'm struggling to follow your explanation.  Can you try to capture what you wish to do in pseudocode?

For example, a clock isn't a counter.

Further, I'm not sure how these two simultaneously running counters are going to impact each other.  Since that was the fundamental basis of your question, that leaves me not understanding.

Just on the wild, off-chance it will help (since I don't really understand your question yet), here's a discussion of how to handle timing logic within an FPGA.

Dan

Link to comment
Share on other sites

Here is the logic part of my encoder ip block after this I write these onto slave registers then read them using sdk and print outputs onto the terminal but it seems like when first if is executing it sometimes doesn't set counter to 0 or doesn't set counted teeth signal to counter. 

Process

Begin

    If (Timer >= 1_000_000) then

        Counted_teeth   <=   counter;

        counter               <=   0;

        Timer                  <=   0;

    End if;

    If (rising_edge(S_AXI_ACLK)) then

        Timer     <=    Timer + 1;

    End if;

    If (rising_edge(Input_bit)) then

        counter    <=   counter + 1;

    End if;

End process;

 

Thanks for helping sorry my English isn't very good. 

 

Link to comment
Share on other sites

@D@n

 

I know my question has already been answered but i'm up against another problem and i didn't think it needed a topic of its own.

I wrote the IP again using your logic and i understand how it works but when i try to generate bitstream it gives combinatorial loop error for the timer. I have faced this issue before while i was designing my PWM block but at the time i just fixed it by making the timer like below is there a better way of fixing this issue.
 

processs (S_AXI_ACLK) is
	if (timer >= 1_000_000)
	then
		timer_stb <= '1';
		timer <= 0;
	else
    		timer_temp <= timer;
		timer <= timer_temp + 1;
		timer_stb <= '0';
	end if;
end process;

 
 

Link to comment
Share on other sites

1 hour ago, Ahmet said:

@D@n

 

I know my question has already been answered but i'm up against another problem and i didn't think it needed a topic of its own.

I wrote the IP again using your logic and i understand how it works but when i try to generate bitstream it gives combinatorial loop error for the timer. I have faced this issue before while i was designing my PWM block but at the time i just fixed it by making the timer like below is there a better way of fixing this issue.
 


processs (S_AXI_ACLK) is
	if (timer >= 1_000_000)
	then
		timer_stb <= '1';
		timer <= 0;
	else
    		timer_temp <= timer;
		timer <= timer_temp + 1;
		timer_stb <= '0';
	end if;
end process;

 
 

I have found my issue.  it was not using rising_edge,  in vhdl we have to use rising_edge in an if so doing that has solved it. Thanks for everything.  

Link to comment
Share on other sites

For reference for anyone reading this thread in the future, the likely solution here was probably something like the following code:

process begin
	if (rising_edge(S_AXI_ACLK)) then
		if (timer >= 1_000_000) then
			timer_stb <= '1';
			timer <= 0;
		else
			timer_temp <= timer;
			timer <= timer_temp + 1;
			timer_stb <= '0';
		end if;
	end if;
end process;

(based on the above provided code, I have not tested this myself)

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...