Merge pull request #167 from WhiteNinjaZ/button_controll

De-bounce example
This commit is contained in:
Tomasz Michalak 2021-08-19 12:08:21 +02:00 committed by GitHub
commit 12840ae407
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 343 additions and 1 deletions

View File

@ -47,7 +47,7 @@ shift
examples="$@"
if [ "$fpga_family" == "xc7" -a -z "$examples" ]; then
examples="counter picosoc litex litex_linux"
examples="counter picosoc litex litex_linux button_controller"
elif [ "$fpga_family" == "eos-s3" -a -z "$examples" ]; then
examples="counter"
fi
@ -55,6 +55,7 @@ fi
# activate conda and enter example dir
snippets="docs/building-examples.rst:export-install-dir,fpga-fam-$fpga_family,conda-prep-env-$fpga_family,conda-act-env,enter-dir-$fpga_family"
additionalDesigns="docs/building-examples.rst:export-install-dir,fpga-fam-$fpga_family,conda-prep-env-$fpga_family,conda-act-env,enter-dir-$fpga_family,additional_examples"
# Xilinx 7-Series examples
if [ "$fpga_family" = "xc7" ]; then
@ -72,6 +73,11 @@ if [ "$fpga_family" = "xc7" ]; then
"litex_linux")
snippets="${snippets} xc7/linux_litex_demo/README.rst:example-litex-*-group"
;;
#Additional examples:
"button_controller")
snippets="${additionalDesigns} xc7/additional_examples/button_controller/README.rst:example-debouncer-basys3"
;;
*)
echo "ERROR: Unknown example name: $example" >&2
exit 1

View File

@ -57,6 +57,15 @@ jobs:
- {fpga-fam: "xc7", os: "debian", os-version: "buster", example: "litex_linux"}
- {fpga-fam: "xc7", os: "debian", os-version: "bullseye", example: "litex_linux"}
- {fpga-fam: "xc7", os: "debian", os-version: "sid", example: "litex_linux"}
- {fpga-fam: "xc7", os: "ubuntu", os-version: "xenial", example: "button_controller"}
- {fpga-fam: "xc7", os: "ubuntu", os-version: "bionic", example: "button_controller"}
- {fpga-fam: "xc7", os: "ubuntu", os-version: "focal", example: "button_controller"}
- {fpga-fam: "xc7", os: "centos", os-version: "7", example: "button_controller"}
- {fpga-fam: "xc7", os: "centos", os-version: "8", example: "button_controller"}
- {fpga-fam: "xc7", os: "debian", os-version: "buster", example: "button_controller"}
- {fpga-fam: "xc7", os: "debian", os-version: "bullseye", example: "button_controller"}
- {fpga-fam: "xc7", os: "debian", os-version: "sid", example: "button_controller"}
env:
LANG: "en_US.UTF-8"

View File

@ -91,6 +91,16 @@ Enter the directory that contains examples for Xilinx 7-Series FPGAs:
.. jinja:: xc7_linux_litex_demo
:file: templates/example.jinja
Additional Examples
-------------------
In addition to the designs we have gone over here, you can also find several other exciting designs
for the basys3 board in the additional_examples directory:
.. code-block:: bash
:name: additional_examples
cd additional_examples
QuickLogic EOS S3
-----------------

BIN
docs/images/pwm.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB

BIN
docs/images/timer.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

View File

@ -0,0 +1,8 @@
current_dir := ${CURDIR}
TARGET := basys3
TOP := top
SOURCES := ${current_dir}/*.sv
XDC := ${current_dir}/basys3.xdc
include ${current_dir}/../../../common/Makefile

View File

@ -0,0 +1,41 @@
Button Controller
~~~~~~~~~~~~~~~~~
This example demonstrates using a button debouncer state machine to count the number of presses on the
center button of the basys3 board. The number of presses counted by the debouncer state machine will
be given on the two right most digits of the display. The two left most digits record the number of
presses counted without the debouncer. You can reset the button counter by pressing the up button on
the board. To build the design first navigate to the additional examples directory:
.. code-block:: bash
:name: additional-examples
cd additional_examples
Then run make to compile the design:
.. code-block:: bash
:name: example-debouncer-basys3
make -C button_controller
At completion, the bitstream is located in the build directory:
.. code-block:: bash
cd button_controller/build/basys3
Now, you can upload the design with:
.. code-block:: bash
openocd -f ${INSTALL_DIR}/${FPGA_FAM}/conda/envs/${FPGA_FAM}/share/openocd/scripts/board/digilent_arty.cfg -c "init; pld load 0 top.bit; exit"
The following is an example of the debouncer in action:
.. image:: ../images/debounce.gif
:align: center
:width: 50%

View File

@ -0,0 +1,38 @@
# Clock
set_property PACKAGE_PIN W5 [get_ports { clk }];
set_property IOSTANDARD LVCMOS33 [get_ports { clk }];
# Buttons
set_property PACKAGE_PIN U18 [get_ports { btnc }];
set_property IOSTANDARD LVCMOS33 [get_ports { btnc }];
set_property PACKAGE_PIN T18 [get_ports { btnu }];
set_property IOSTANDARD LVCMOS33 [get_ports { btnu }];
# Seven-Segment Display
set_property PACKAGE_PIN W7 [get_ports { segment[0] }];
set_property PACKAGE_PIN W6 [get_ports { segment[1] }];
set_property PACKAGE_PIN U8 [get_ports { segment[2] }];
set_property PACKAGE_PIN V8 [get_ports { segment[3] }];
set_property PACKAGE_PIN U5 [get_ports { segment[4] }];
set_property PACKAGE_PIN V5 [get_ports { segment[5] }];
set_property PACKAGE_PIN U7 [get_ports { segment[6] }];
set_property PACKAGE_PIN V7 [get_ports { segment[7] }];
set_property IOSTANDARD LVCMOS33 [get_ports { segment[0] }];
set_property IOSTANDARD LVCMOS33 [get_ports { segment[1] }];
set_property IOSTANDARD LVCMOS33 [get_ports { segment[2] }];
set_property IOSTANDARD LVCMOS33 [get_ports { segment[3] }];
set_property IOSTANDARD LVCMOS33 [get_ports { segment[4] }];
set_property IOSTANDARD LVCMOS33 [get_ports { segment[5] }];
set_property IOSTANDARD LVCMOS33 [get_ports { segment[6] }];
set_property IOSTANDARD LVCMOS33 [get_ports { segment[7] }];
# Anodes
set_property PACKAGE_PIN U2 [get_ports { anode[0] }];
set_property PACKAGE_PIN U4 [get_ports { anode[1] }];
set_property PACKAGE_PIN V4 [get_ports { anode[2] }];
set_property PACKAGE_PIN W4 [get_ports { anode[3] }];
# Clock constraints
create_clock -period 10.0 [get_ports {clk}]

View File

@ -0,0 +1,71 @@
`timescale 1ns / 1ps `default_nettype none
module top (
input wire logic clk,
btnu,
btnc,
output logic [3:0] anode,
output logic [7:0] segment
);
logic sync;
logic syncToDebounce;
logic debounceToOneShot;
logic f1, f2;
logic f3, f4;
logic oneShotToCounter;
logic [7:0] counterToSevenSegment;
logic [7:0] counterToSevenSegment2;
logic oneShotToCounter2;
logic s0, s1;
debounce d0 (
.clk(clk),
.reset(btnu),
.noisy(syncToDebounce),
.debounced(debounceToOneShot)
);
assign oneShotToCounter = f1 && ~f2;
assign oneShotToCounter2 = f3 && ~f4;
timer #(.MOD_VALUE(256), .BIT_WIDTH(8)) T0 (
.clk(clk),
.reset(btnu),
.increment(oneShotToCounter),
.rolling_over(s0),
.count(counterToSevenSegment)
);
timer #(.MOD_VALUE(256), .BIT_WIDTH(8)) T1 (
.clk(clk),
.reset(btnu),
.increment(oneShotToCounter2),
.rolling_over(s1),
.count(counterToSevenSegment2)
);
display_control DC0 (
.clk(clk),
.reset(btnu),
.dataIn({counterToSevenSegment2, counterToSevenSegment}),
.digitDisplay(4'b1111),
.digitPoint(4'b0000),
.anode(anode),
.segment(segment)
);
always_ff @(posedge clk) begin
sync <= btnc;
syncToDebounce <= sync;
f1 <= debounceToOneShot;
f2 <= f1;
f3 <= syncToDebounce;
f4 <= f3;
end
endmodule

View File

@ -0,0 +1,64 @@
`timescale 1ns / 1ps `default_nettype none
module debounce (
input wire logic clk,
reset,
noisy,
output logic debounced
);
logic timerDone, clrTimer;
typedef enum logic [1:0] {
s0,
s1,
s2,
s3,
ERR = 'X
} state_type_e;
state_type_e ns, cs;
logic [18:0] tA;
timer #(.MOD_VALUE(500000), .BIT_WIDTH(19)) T0 (
.clk(clk),
.reset(clrTimer),
.increment(1'b1),
.rolling_over(timerDone),
.count(tA)
);
always_comb begin
ns = ERR;
clrTimer = 0;
debounced = 0;
if (reset) ns = s0;
else
case (cs)
s0: begin
clrTimer = 1'b1;
if (noisy) ns = s1;
else ns = s0;
end
s1:
if (noisy && timerDone) ns = s2;
else if (noisy && ~timerDone) ns = s1;
else ns = s0;
s2: begin
debounced = 1'b1;
clrTimer = 1'b1;
if (noisy) ns = s2;
else ns = s3;
end
s3: begin
debounced = 1'b1;
if (~noisy && timerDone) ns = s0;
else if (~noisy && ~timerDone) ns = s3;
else ns = s2;
end
endcase
end
always_ff @(posedge clk) cs <= ns;
endmodule

View File

@ -0,0 +1,67 @@
`default_nettype none
module display_control (
input wire logic clk,
input wire logic reset,
input wire logic [15:0] dataIn,
input wire logic [ 3:0] digitDisplay,
input wire logic [ 3:0] digitPoint,
output logic [ 3:0] anode,
output logic [ 7:0] segment
);
parameter integer COUNT_BITS = 17;
logic [COUNT_BITS-1:0] count_val;
logic [ 1:0] anode_select;
logic [ 3:0] cur_anode;
logic [ 3:0] cur_data_in;
always_ff @(posedge clk) begin
if (reset) count_val <= 0;
else count_val <= count_val + 1;
end
assign anode_select = count_val[COUNT_BITS-1:COUNT_BITS-2];
assign cur_anode =
(anode_select == 2'b00) ? 4'b1110 :
(anode_select == 2'b01) ? 4'b1101 :
(anode_select == 2'b10) ? 4'b1011 :
4'b0111;
assign anode = cur_anode | (~digitDisplay);
assign cur_data_in =
(anode_select == 2'b00) ? dataIn[3:0] :
(anode_select == 2'b01) ? dataIn[7:4] :
(anode_select == 2'b10) ? dataIn[11:8] :
dataIn[15:12] ;
assign segment[7] =
(anode_select == 2'b00) ? ~digitPoint[0] :
(anode_select == 2'b01) ? ~digitPoint[1] :
(anode_select == 2'b10) ? ~digitPoint[2] :
~digitPoint[3] ;
assign segment[6:0] =
(cur_data_in == 0) ? 7'b1000000 :
(cur_data_in == 1) ? 7'b1111001 :
(cur_data_in == 2) ? 7'b0100100 :
(cur_data_in == 3) ? 7'b0110000 :
(cur_data_in == 4) ? 7'b0011001 :
(cur_data_in == 5) ? 7'b0010010 :
(cur_data_in == 6) ? 7'b0000010 :
(cur_data_in == 7) ? 7'b1111000 :
(cur_data_in == 8) ? 7'b0000000 :
(cur_data_in == 9) ? 7'b0010000 :
(cur_data_in == 10) ? 7'b0001000 :
(cur_data_in == 11) ? 7'b0000011 :
(cur_data_in == 12) ? 7'b1000110 :
(cur_data_in == 13) ? 7'b0100001 :
(cur_data_in == 14) ? 7'b0000110 :
7'b0001110;
endmodule

View File

@ -0,0 +1,28 @@
`timescale 1ns / 1ps `default_nettype none
module timer #(
parameter MOD_VALUE = 1,
parameter BIT_WIDTH = 1
) (
input wire logic clk,
reset,
increment,
output logic rolling_over,
output logic [BIT_WIDTH-1:0] count = 0
);
always_ff @(posedge clk) begin
if (reset) count <= 0;
else if (increment) begin
if (rolling_over) count <= 0;
else count <= count + 1'b1;
end
end
always_comb begin
if (increment && (count == MOD_VALUE - 1)) rolling_over = 1'b1;
else rolling_over = 1'b0;
end
endmodule

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 MiB