{"id":1074,"date":"2025-10-10T16:20:45","date_gmt":"2025-10-10T08:20:45","guid":{"rendered":"https:\/\/vm1.go2see.me\/?p=1074"},"modified":"2025-10-10T16:31:20","modified_gmt":"2025-10-10T08:31:20","slug":"1074","status":"publish","type":"post","link":"https:\/\/vm1.go2see.me\/?p=1074","title":{"rendered":""},"content":{"rendered":"<h1>Lab 6: Combination Lock &amp; Keypad, Part 2<\/h1>\n<p>You must work on this lab with a partner. V1.  <\/p>\n<h2>Objective<\/h2>\n<p>The purpose of this lab is to learn to design more complicated FSMs to drive an external logic circuit.  You will use behavioural SystemVerilog design with Quartus.  Similar to Lab 5, design a circuit that locks and unlocks a safe that you might find in a hotel room. In this  lab, however, you will use a numeric keypad to enter the combination. <\/p>\n<ul>\n<li>To lock the safe, enter any combination as a 6-digit password and press # <\/li>\n<li>To unlock the safe, enter the same password and press # <\/li>\n<li>When entering the password, press * to cancel and start over <\/li>\n<li>When ready to start accepting a password, display <em>OPEn<\/em> or LOCHED, as appropriate <\/li>\n<li>For visual confirmation, incrementally display the password as each key is pressed  <\/li>\n<\/ul>\n<h2>1. Equipment<\/h2>\n<p>You will need: <\/p>\n<ul>\n<li>Two FPGA boards (DE10-Lite and DE1-SoC) and two computers <\/li>\n<li>One 16-key (4&#215;4) numeric keypad with keys labelled 0 to 9, A to D, # (aka E) and * (aka F) <\/li>\n<li>Prebuilt jumper wires (the rainbow cable) with male (M) and female (F) ends:\n<ul>\n<li>8+7 MM (two DE10), 8 MM + 7 MF (mixed boards), 7 FF + 8 MF (two DE1) <\/li>\n<li>Note: two DE1-SoC boards require FF cables that are NOT included in your Parts kit.  <\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>This lab will be implemented as two separate designs on two connected FPGA boards: <\/p>\n<ul>\n<li>keyboard accepts user input, debounces the pressed key, and both displays\/transmits it <\/li>\n<li>combo receives a key from keyboard and displays the password entry, <em>OPEn<\/em> or LOCHED <\/li>\n<li>students without a partner will design the keyboard module to use only one FPGA board  <\/li>\n<\/ul>\n<p>A precompiled golden reference solution for each module is available as a bitstream (.SOF file) for both  DE10-Lite and DE1-SoC boards, allowing you to test against a known working solution for each design.   <\/p>\n<p>Start early \u2013 this lab will be more challenging than previous labs. If you fail to get one module working,  you may use the reference solution to demonstrate that your other module works properly.  <\/p>\n<p>The most difficult part of this lab is metastability and keypad switch bounce, so it is provided to you on  Canvas as a SystemVerilog module key_db.  <\/p>\n<h2>2. Overall Design<\/h2>\n<p>Begin by testing your keypad. Connect it to your FPGA board according to the figure below and use the  golden reference solution keyboard.sof on Canvas. All 16 keys should work reliably with the golden  reference solution for either FPGA board (even the DE1-SoC).<\/p>\n<p>If there is a problem with your keypad, get a replacement from the instructor. Note: when writing your  own keyboard module, it will probably be easier to get reliable operation with the DE10-Lite. Reliable  performance with the DE1-SoC is tricky; tips to improve reliability will be provided below.  <\/p>\n<p>Figure 1. Wiring diagram.<br \/>\nFigure 2. Block diagram and information flow.  <\/p>\n<p>Build and test your solution incrementally:  <\/p>\n<ol>\n<li>Test your equipment\n<ul>\n<li>connect your boards and keypad together <\/li>\n<li>using the two golden reference solutions <\/li>\n<li>test the keypad and wiring to the golden keyboard module <\/li>\n<li>test the wiring to the golden combo module  <\/li>\n<\/ul>\n<\/li>\n<li>Build and test your SystemVerilog modules independently\n<ul>\n<li>combo module tips\n<ul>\n<li>start using simulation and a testbench: you can also print Verilog debug messages  with statement $display(\u201c<em>OPEn<\/em>\u201d); or $display(\u201cLOCHED\u201d); <\/li>\n<li>single-board testing: use KEY[0] to manually clock your FSM, SW[3:0] to  provide  keycode[3:0] input values and ~KEY[1] to simulate valid <\/li>\n<li>multi-board testing: connect to the golden reference keyboard solution <\/li>\n<\/ul>\n<\/li>\n<li>keyboard module tips\n<ul>\n<li>start using simulation and a testbench <\/li>\n<li>use the 7-segment display to display the last 6 key presses <\/li>\n<li>single-board testing: use KEY[0] to manually clock your FSM, SW[7:0] to  provide {row, col} input values, and ~KEY[1] to simulate a keypress <\/li>\n<li>multi-board testing: connect to the golden reference combo solution  <\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>Finally, connect your two modules together!  <\/li>\n<\/ol>\n<h2>3. Inout Wires and GPIO Connections<\/h2>\n<p>The connections between FPGA boards, and from FPGA board to keypad, will be using some general purpose input\/output (I\/O) pins on the PCB. Each pin can be configured to be either an input pin, or an  output pin, or both (bidirectional).  <\/p>\n<p>On the DE10-Lite, we will be using the two Arduino connectors labelled J2 and J3 on the PCB. <\/p>\n<ul>\n<li>These female connectors accept a male (M) wire end. <\/li>\n<li>In SystemVerilog, these signals are named ARDUINO_IO[15:0]. See Figure 1.  <\/li>\n<\/ul>\n<p>On the DE1-SoC, we will be using the GPIO_1 connector<br \/>\nalso labelled JP2 on the PCB. <\/p>\n<ul>\n<li>These are called \u2018header connectors\u2019 with male pins, so they accept a female (F) wire end. <\/li>\n<li>In SystemVerilog, these signals are named GPIO_1[35:0]. See Figure 1.  <\/li>\n<\/ul>\n<p>For both DE10-Lite and DE1-SoC connectors, the location of connector pin 1 can be confirmed on the  bottom side of the circuit board by the square solder joint. The DE1-SoC also has a cutout in the plastic  shroud on the top side next to pins 19 and 21.  <\/p>\n<p>The keypad accepts male (M) wire ends. Connecting the keypad to a DE10-Lite requires MM cables,  while connecting to a DE1-SoC requires MF cables. Both of these cable types are in your electronics kit.  <\/p>\n<p>Connecting DE10-Lite to DE10-Lite requires MM cables, while connecting DE10-Lite to DE1-SoC  requires MF cables. Again, these are the same cables in your electronics kit.<br \/>\nConnecting two DE1-SoCs requires FF cables, but these are not included in your electronics kit. While  not ideal, you can use your breadboard to connect two male ends of two MF cables.<br \/>\nIn SystemVerilog, connections to these general-purpose I\/O signals should be declared as type  \u2018inout wire\u2019.<br \/>\nUsing \u2018input logic\u2019 or \u2018output logic\u2019 also works when all of the pins are the  same direction (ie, all inputs or all outputs). However, the \u2018inout wire\u2019 declaration allows you to set  the direction of each pin separately, including using the pin as a bidirectional pin (using a tri-state gate);  inside your logic module, use a continuous assignment statement to clearly indicate your intent, e.g.:  <\/p>\n<pre><code class=\"language-verilog\">logic [3:0] row, col;  \nassign ARDUINO_IO[7:4] = row;  \nassign col = ARDUINO_IO[3:0];<\/code><\/pre>\n<h2>4. Combo Module<\/h2>\n<p>The combo module implements the FSM that allows the user to operate the safe as described in the  Objective section.<br \/>\nIt uses the 7-segment display to show the current state of the FSM, including open,  unlocked, or a partially entered password.<br \/>\nThe inputs to the FSM come from the keyboard module implemented on a separate FPGA board, giving  rise to a few important technical issues: <\/p>\n<ul>\n<li>You must connect the Ground (0V) between boards so they have a common reference voltage.  Without this, the receiving board will not know the proper voltage being supplied by the other  board, so it may consider the input to be in the forbidden zone or misinterpret the 0 or 1 value. <\/li>\n<li>Do NOT connect +5V or +3.3V or any other power signals. The two boards have independent  power supplies; any small differences in their voltage would cause the two power supplies to  draw a large current from one with the higher voltage. <\/li>\n<li>Although both boards have highly accurate 50MHz clock, these clocks operate independently and  will not perfectly matched; one is likely to be a bit faster than the others, and the edges will never  be perfectly coincident (called phase alignment). For reliable communications, we will practice  some simple rules:\n<ul>\n<li>To avoid metastability, the receiver must use a synchronizer. This means each of the 5  signals (valid and keycode[3:0]) must pass through two flip-flops in series, all  clocked by the receiver\u2019s clock. Call these synchronized signals valid_ff and  keycode_ff[3:0]. <\/li>\n<li>The transmitter must hold the valid and keycode[3:0] signals constant for at least  3 cycles so the receiver has time to recognize the inputs even if its clock is faster. <\/li>\n<li>After the synchronizer, the receiver must sample keycode_ff[3:0] one cycle after it  sees valid_ff go high. Sampling a set of parallel signals on the same cycle its valid  signal is asserted could lead to incorrect results; if any of the signals (including the valid  signal) is delayed (or advanced) by a small amount and\/or fails to meet the setup time of  its flip-flop, its value may appear one cycle early, or it may one cycle later, than the other  signals. Ensuring all signals are constant (stable) for 3 cycles and trying to sample in the  middle of that time period is a simple and safe way to ensure success. <\/li>\n<li>There are many other ways this could be done in practice, including: source-synchronous  transmission, phase-locking clocks with PLLs, distributing globally phase-aligned clocks,  sending data and clock and recovering them on the other end through clock-data  recovery, and asynchronous transmission over a serial wire (see UART in Wikipedia).  Don\u2019t attempt any of these!  <\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2>5. Keyboard Module<\/h2>\n<p>The keyboard module continuously scans the keypad and transmits each key press to another module.<br \/>\nIt is governed by an FSM that must take into account a few technical issues: <\/p>\n<ul>\n<li>The user can press a key at any time relative to the clock, so metastability is a concern. <\/li>\n<li>The key may bounce. <\/li>\n<li>Holding a key down should result in a single keypress, not constant keypresses. <\/li>\n<li>The # and * keys will transmit keycodes 4\u2019hE and 4\u2019hF, respectively. Other keys (0-9, A-D) will  transmit their regular 4-bit hexadecimal encoding. <\/li>\n<li>The combo module protocol requires keycode and valid to be held constant for at least 3 cycles  for each keypress.   <\/li>\n<\/ul>\n<p>The first two issues are quite serious, so we have written a SystemVerilog module called kb_db to  perform debouncing and resolve metastability.<br \/>\nHowever, your FSM must resolve all of the other issues.<br \/>\nBelow is a PRELIMINARY VERSION of kb_db \u2013 note how &lt;= is used inside always_ff and = is  used inside always_comb. The pressed output is set as soon as a keypress is detected, allowing you  to sample col_F1 and row_F1, but wait until debounceOK is also set before checking for the key to  be released. You should also wait for debounceOK to be set after you detect a released key.  <\/p>\n<pre><code class=\"language-verilog\">module kb_db #( DELAY=20 ) ( \n input logic  clk, \n input logic  rst, \n inout wire   [7:0] ARDUINO_IO, \n input logic  [3:0] fsm_row_F0, \n output logic [3:0] col_F1, \n output logic [3:0] row_F1, \n output logic  pressed, \n output logic  debounceOK \n); \n\n logic [DELAY:0]  counter; \n logic [3:0] kb_col_L0; \n logic press_L1, press_F2, edge_L1; \n\n assign ARDUINO_IO[7:4] = fsm_row_F0; \n assign kb_col_L0   = ARDUINO_IO[3:0]; \n\n assign pressed   = press_L1; \n assign debounceOK  = counter[DELAY]; \n\n \/\/ edge detection \n always_comb begin \n  press_L1   = ~&amp;( col_F1[3:0] ); \n  edge_L1   = press_L1 ^ press_F2; \n end \n \/\/ edge detection and synchronizers \n always_ff @( posedge clk ) begin \n  col_F1 &lt;= kb_col_L0; \n  row_F1 &lt;= fsm_row_F0; \n  press_F2 &lt;= press_L1; \n end \n\n \/\/ debounce counter \n initial counter = 0; \n always_ff @( posedge clk ) begin \n  if( rst | edge_L1 ) begin \n   counter &lt;= 0; \n  end else if( !debounceOK ) begin \n   counter &lt;= counter+1; \n  end \n end \n\nendmodule \n<\/code><\/pre>\n<p>To decode which key is pressed on the keypad, note: <\/p>\n<ul>\n<li>A keypad is incredibly simple: pressing a specific key results in a simple connection between one  specific row wire and one specific column wire. For the 4&#215;4 keypad, there are 4 row wires and 4  column wires; the FSM must determine which key is pressed and transmit the corresponding 4-bit  keycode. <\/li>\n<li>When no key is pressed, the 4 column wires are floating. To make them appear as a logic 1  instead, connect all 4 column wires to Vdd through a pull-up resistor.\n<ul>\n<li>For this, enable a weak pullup resistor on FPGA inputs, reportedly 50-500 kOhm. <\/li>\n<\/ul>\n<\/li>\n<li>When a key is pressed, it connects the key\u2019s column wire to its row wire.\n<ul>\n<li>To determine which column, look for the 0 on the four column wires. <\/li>\n<li>To determine which row, you need to scan row-by-row with the FSM: <\/li>\n<li>Output a 1 to all row wires except the row being scanned which should have a 0. <\/li>\n<li>Pressing any key on that row will send the respective column wire to 0; all other  column wires remain 1 due to the pull-up resistor.  <\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>In addition to the keypad scanning just explained, there are some issues of timing to note: <\/p>\n<ul>\n<li>Releasing a key requires its column wire to be restored to Vdd through a weak pull-up resistor in  the FPGA. How long does this take? With a 500kOhm resistor, it could take several (tens?  hundreds?) of clock cycles. You should wait long enough for this to occur (e.g., one debounce  period after the key is released. <\/li>\n<li>They keypad itself has an internal resistance of 50-500 Ohms (measure it!) when a key is pressed.  This limits how rapidly the FPGA row output pin can pull down the column wire. On the DE10 Lite it appears that 2 clock cycles is long enough. On the DE1-SoC, this appears to take 3 clock  cycles. I do not recommend attempting to speed this up. <\/li>\n<li>Because of the synchronizer flip-flops and debounce detection in kb_db, you cannot sample the  column inputs immediately the row outputs are set. The 2 or 3 cycles of waiting needed (as  explained in the previous bullet) also covers this delay.  <\/li>\n<\/ul>\n<p>Add 4 weak pull-up resistors to the column GPIO pins: <\/p>\n<ul>\n<li>Quartus \u00e0 Assignments \u00e0 Assignment Editor \u00e0 scroll to bottom \u00e0 in the \u201cTo\u201d column, enter  a pin name (e.g., ARDUINO_IO[0]) where it says &lt;&gt; \u00e0 in the \u201cAssignment Name\u201d  column, double-click and select \u201cWeak Pull-Up Resistor\u201d near the bottom \u00e0in the \u201cValue\u201d  column, double-click and select \u201cOn\u201d \u00e0 in the \u201cEnabled\u201d column, make sure it says \u201cYes\u201d. <\/li>\n<li>Repeat for each of the other 3 column inputs (e.g., ARDUINO_IO[1], ARDUINO_IO[2], and  ARDUINO_IO[3]).  <\/li>\n<\/ul>\n<h2>6. Putting it All Together<\/h2>\n<p>When you think your combo and keyboard modules are both 100% correct (and each works with the  corresponding golden reference solution), you are ready to try the whole thing. Good luck!  <\/p>\n<h2>7. What to Turn In and Demonstrate<\/h2>\n<p>TBD. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lab 6: Combination Lock &amp; Keypad, Part 2 You must w&#8230; &raquo; <a class=\"read-more-link\" href=\"https:\/\/vm1.go2see.me\/?p=1074\">\u95b1\u8b80\u5168\u6587<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1074","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/vm1.go2see.me\/index.php?rest_route=\/wp\/v2\/posts\/1074","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vm1.go2see.me\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vm1.go2see.me\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vm1.go2see.me\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/vm1.go2see.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1074"}],"version-history":[{"count":3,"href":"https:\/\/vm1.go2see.me\/index.php?rest_route=\/wp\/v2\/posts\/1074\/revisions"}],"predecessor-version":[{"id":1076,"href":"https:\/\/vm1.go2see.me\/index.php?rest_route=\/wp\/v2\/posts\/1074\/revisions\/1076"}],"wp:attachment":[{"href":"https:\/\/vm1.go2see.me\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1074"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vm1.go2see.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1074"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vm1.go2see.me\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1074"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}