Jump to content
  • 0

Newbie question about binary counter on Basys3


rafauy

Question

Hi Everyone,

I tried some tutorials and the forum but couldn't find much help with this. Im using a Basys3 board with Vivado ISE webpack.

I want to make a 5 bit binary counter that increments every time C button is pressed and the value is displayed in 5 leds.

I wrote the following code:

module Adder32(input wire btnC, input wire clk, output reg [4:0] led);

    always @(posedge btnC)
        if (0) begin
            led <= 5'b0;
        end else if(1) begin
            led = led + 1;
        end
endmodule

If I change the always trigger condition to posedge clk it works fine (The leds turn on and off so fast I barely see anything but with an oscilloscope it can be seen),

but when I want to trigger the counter with the C button I get these errors when generating the bitstream:

  • [Place 30-574] Poor placement for routing between an IO pin and BUFG. If this sub optimal condition is acceptable for this design, you may use the CLOCK_DEDICATED_ROUTE constraint in the .xdc file to demote this message to a WARNING. However, the use of this override is highly discouraged. These examples can be used directly in the .xdc file to override this clock rule. < set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets btnC_IBUF] > btnC_IBUF_inst (IBUF.O) is locked to IOB_X0Y13 and btnC_IBUF_BUFG_inst (BUFG.I) is provisionally placed by clockplacer on BUFGCTRL_X0Y0
  • [Place 30-99] Placer failed with error: 'IO Clock Placer failed' Please review all ERROR, CRITICAL WARNING, and WARNING messages during placement to understand the cause for failure.
  • [Common 17-69] Command failed: Placer could not place all instances

I tried including/excluding clock constraints and the clock from the modules parameter list, all possible combinations, nothing helped (the errors change).

 

My constraints are:

set_property PACKAGE_PIN W5 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk]

set_property PACKAGE_PIN U16 [get_ports {led[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}]
set_property PACKAGE_PIN E19 [get_ports {led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}]
set_property PACKAGE_PIN U19 [get_ports {led[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}]
set_property PACKAGE_PIN V19 [get_ports {led[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}]
set_property PACKAGE_PIN W18 [get_ports {led[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[4]}]

set_property PACKAGE_PIN U18 [get_ports btnC]
set_property IOSTANDARD LVCMOS33 [get_ports btnC]

set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 33 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]

Thanks!

 

 

 

Link to comment
Share on other sites

10 answers to this question

Recommended Posts

@rafauy

That error is likely coming from "always@(posedge btnC)". Triggering logic on non-clock pins is generally considered a no-no, and the push buttons generate particularly noisy signals. Whenever you press or release the button, the signal will actually flip high and low a bunch of times before settling into the new state. A suggested way to fix your errors would be to use code with a structure like the following:

always@(posedge clk) begin
	if (strobe_BtnC == 1)
		do stuff;
end

There are a few differences here, first, posedge clk. Logic should almost always be driven from a clock, you can likely find a number of other posts around the forums about why this better than the alternatives. Second, strobe_BtnC is a new signal that is being introduced. This signal should be high for only one clock cycle, and should only be high once per press of the center button. There are a few typical verilog patterns to look into here. A synchronizer will properly bring your button signal into your clock domain. A debouncer will remove the significant jittering of the button signal. An Edge Detection circuit (typically paired with your synchronizer, though not necessarily) will limit your counter to one increment per button press.

Some possible reading material for you to check out: On clock domains at ASIC World. A decent description of why debouncers need to be used at fpga4fun. More description of synchronizers and edge detection at doulos.com.

Hope this helps,

Arthur

Link to comment
Share on other sites

@artvvb and @Alex

Could you, please, for my education explain why is it bad to drive logic without a clock. I can agree that when you have two periodic signals a synchonizer is a must. However, this case is of combinational logic driven by pretty much random event. I don't see compelling reason to for adding a clock.

Perhaps, one practical reason for a clock is for the debouncer. Push buttons without debouncer are hardly usable with FPGAs.

I can also see that Xilinx router might have troubles to set timing constraints. Routing error indicates that this might be the problem.

Thank you

 

Link to comment
Share on other sites

@Notarobot,

I spent some time a while ago looking for the "official" Xilinx answer on this.

I didn't find the "Don't use anything other than a clock for a positive edge" answer that I was looking for.  (I still give this answer to beginners anyway, though.)

The "official" answer that I found on Xilinx's forums was: Make sure you understand the hardware first.  Understand what it is you really want the hardware to do, and how it will do it, and then ... go ahead and knock yourself out.

Sadly, after finding that post, I didn't keep track of it 'cause ... It didn't fit my agenda.  :D

In this case, because of the whole bouncing issue, I'm also going to highly recommend using a proper clock.

Dan

Link to comment
Share on other sites

I have to add that recently I had to pay special attention to custom timing constraints on my project. This was a key factor for achieving 1) stable performance and 2) comfortable level of confidence. Unfortunately, it rarely discussed on this forum.

Link to comment
Share on other sites

@Notarobot I agree with @Dan. Perhaps we firstly need to understand the logic and signal characteristics, we can create the digital design. From what I learn so far (still pretty basic digital design), you may not need a clock for asynchronous circuit. I don't know if this section is good to start the educational topic. There is educational topic in this forum 

Link to comment
Share on other sites

@Alex,

Some time ago, I needed to build a system that was almost *all* asynchronous.  Sure, it had a clock, but one of the interfaces had to respond as fast as possible and another computer, external to the FPGA, controlled that interface and the FPGA was just a pass through in that case.  Well ... a pass through with a clocked override if necessary.

So ... it's doable, but definitely not something you'd want to encourage a beginner to try until he'd learned more of the basics.

As for educational topics, I'm trying to hit quite a few with a blog I've been working on.  You can find some of the recent topics here, with the last post about how to minimize the logic usage within an FPGA.  At the start of next semester, I'm hoping to post a list of my "rules for beginners."  Doing everything synchronously will be one of those rules.  If you are otherwise looking for a forum for a "lesson" for beginners, feel free to contact me about posting one.  I'd be glad to put it on the blog.

Dan

P.S.  I was a pretty green beginner when I did it too ...

Link to comment
Share on other sites

11 hours ago, Notarobot said:

Could you, please, for my education explain why is it bad to drive logic without a clock. I can agree that when you have two periodic signals a synchonizer is a must. However, this case is of combinational logic driven by pretty much random event. I don't see compelling reason to for adding a clock.

 

A few reasons are...

a - The introduction of logic hazards can cause glitches : https://en.wikipedia.org/wiki/Hazard_(logic)

b - Routing of clocks is very complex - It is hard to ensure that the same clock edge appears all over the FPGA at almost exactly the same time. Sometimes this is achieved with 'slight of hand' (e.g. using a on-chip PLL to advance phase of the clock, so that by the time it reaches the edge of the chip is in back phase with the original signal). Low-skew paths also exist, but are restricted to small areas of the FPGA, and the clock has to be connected to the correct pin to be placed and routed correctly.

c - FPGAs and their tools are designed to behave predictably under the "synchronous digital design" paradigm (something like https://hps.hs-regensburg.de/scm39115/homepage/education/courses/red/2_SynchronousDigitalCircuitDesignRules.pdf). If you work outside the paradigm you will be fighting against the tools and their assumptions.

d - There is almost nothing that you are unable to code in an FPGA friendly way, but there are infinitely many ways to write FPGA-hostile code. If you want your FPGA to place nice with you, you have to play nice with it.

So you can either add an RC filter to debounce you switch, or you can sample it using a reliable clock.

Link to comment
Share on other sites

19 hours ago, hamster said:

 

@hamster

Thank you for work putting this all together. 

Only one note. All a-d points are valid but unavoidable. There is no way to avoid time races. Every bus has this issue. The key is to keep these issues under control using timing constraints. Luckily, Xilinx does a good job checking various paths and warning about bad conditions. The same of course is true with other manufacturers.

Link to comment
Share on other sites

Archived

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

×
×
  • Create New...