Hi, I'm sorry for this "easy" question but i was cracking my head to understand how to refresh nexys 3 FPGA segment leds constantly with 50Hz, my base clock is 100Mhz and I cant understand how counter should be calculated to get desired value, even after getting the correct value, how to run over each segment and refresh it?
A 100 MHz is a 10 ns period and you need to mark off 50 Hz or 1/50 sec = 0.02 sec, therefore you want a counter that counts from 0-1,999,999 (0.02/10e-9).
Code:
always @ (posedge clk) begin
cntr <= (cntr < 2000000) ? cntr +1 : 0;
end
The question remains though why do you need 50 Hz? The human eye can't distinguish an LED strobing at 50 Hz. I think we can only see it flashing if it's slower than something like 25 ms due to persistence of both our eye and the LED itself.
If you have 4 digits and want to refresh with 50Hz, then you need a frequency of 4 x 50Hz to switch from one digit to the other.
But you don't say how many digits you have.
The Nexys 3 has a 4-digit multiplexed 7-segment display. As KlausST says, you should switch digit at 200 Hz to get a refresh rate of 50 Hz.
It is also possible to scan the other way, turning on one segment at a time for all digits. The switch rate must then be 8 times the refresh rate (7 segments + decimal point) but that holds for any number of digits. If the display has more than 8 digits that should reduce the peak current in the display driver, and I think some TI LED calculators did it that way. Maybe the original TI-30.
okay then the counter needs to cycle for a count of 500000:
Code:
always @ (posedge clk) begin
cntr <= (cntr < 500000) ? cntr +1 : 0;
updated_digit <= ~|cntr;
end
The ~| is a reduction NOR in verilog, so it's updating the display every time the counter reaches 0, as it would be free running, there is no reason to compare the count to 499999, and this method uses less logic to implement.
okay then the counter needs to cycle for a count of 500000:
Code:
always @ (posedge clk) begin
cntr <= (cntr < 500000) ? cntr +1 : 0;
updated_digit <= ~|cntr;
end
The ~| is a reduction NOR in verilog, so it's updating the display every time the counter reaches 0, as it would be free running, there is no reason to compare the count to 499999, and this method uses less logic to implement.
I don't use verilog, but the compare should already be there, so I don't see the point with the "reduction NOR".
The following should use less logic since the reduction NOR will not fit in a single LUT:
Code:
always @ (posedge clk) begin
if (cntr < 500000)
cntr <= cntr + 1;
updated_digit <= 0;
else
cntr <= 0;
updated_digit <= 1; // happens one clock cycle earlier than in the original code
end
The "updated_digit" will be set one clock cycle earlier with this code, but that doesn't matter in this application.
The compare "< 500000" will make the circuit divide by 500001, but maybe that was intentional to reduce the number of bits to compare?
By changing the value to 524288 (hex 80000) the comparator will fit in a single LUT and the refresh frequency will be 47.7 Hz
Okay, turns out my code produces more LUTs due to the reduction NOR, but uses less Slices (Kintex 7 Vivado)
std_match's code uses 1 more Slice and half the LUT count
In one respect my code is better, if you have lot's of control sets each slice is stuck with whatever control set is on it regardless if there are unused resources in that slice.
And the cntr < 500000 is a mistake born from working on a bunch of software loops for the couple of weeks where I'm doing a lot of while (cntr < 200000) type stuff to iterate over ~200,000 lines of data. I've unfortunately been stuck post processing data captures from hardware.