// buttontest.v // // Debounce a button to drive an 8-bit counter. // Use a decoder to drive a custom pattern on 8 output LEDs. // // look in pins.pcf for all the pin names on the TinyFPGA BX board // Pins 2 and 13 have internall pull-up resistors enabled // // Synthesize and download with: // apio build // tinyprog -p hardware.bin // // E.Torrence // PHYS 432 // April 14, 2019 // module top ( input CLK, // 16MHz clock input PIN_2, // Button input input PIN_13, // Button input output LED, // User/boot LED next to power LED output USBPU, // USB pull-up resistor output PIN_14, // 8 LED outputs output PIN_15, output PIN_16, output PIN_17, output PIN_18, output PIN_19, output PIN_20, output PIN_21 ); // drive USB pull-up resistor to '0' to disable USB assign USBPU = 0; // This is our reset button, doesn't need to be debounced wire reset; assign reset = !PIN_13; //////// // drive a counter with a debounced button //////// // Output LED display, 8 bits with MSB first reg [7:0] LEDreg; // Continuously assign the value of ledreg to output pins 14-21 assign {PIN_14, PIN_15, PIN_16, PIN_17, PIN_18, PIN_19, PIN_20, PIN_21} = LEDreg; // Internal counter value reg [7:0] countValue; // Instantiate a button debouncer module, output goes to button1 wire button1; debounce b1(CLK, PIN_2, button1); // Instantiate a counter based on debounced button1 as a clock counter8 count8(button1, reset, countValue); // Alternately, drive counter directly with the raw button input // counter8 count8(PIN_2, reset, countValue); // Use counter value as input to display decoder displaydecoder lut(countValue, LEDreg); // Alternately, display counter value directly on LEDs // assign LEDreg = countValue; // Assign the user LED on the board to our button assign LED = !PIN_2; endmodule // Display decoder/Look-up table module displaydecoder ( input [7:0] state, output [7:0] display ); // LUT is 8 bits wide, 16 entries (4 bits) long reg [7:0] lut [0:15]; initial begin lut[0] <= 8'h00; lut[1] <= 8'h01; lut[2] <= 8'h02; lut[3] <= 8'h04; lut[4] <= 8'h08; lut[5] <= 8'h10; lut[6] <= 8'h20; lut[7] <= 8'h40; lut[8] <= 8'h80; lut[9] <= 8'h40; lut[10] <= 8'h20; lut[11] <= 8'h10; lut[12] <= 8'h08; lut[13] <= 8'h04; lut[14] <= 8'h02; lut[15] <= 8'h01; end assign display = ~lut[state[3:0]]; endmodule // Debounce function // Button input must be the same for 4x4ms in a row // to trigger change in output value // Input is system 16 MHz clock // module debounce ( input clock, input button, output value ); reg value; // Make a divide by 16 clock (16 MHz / 2^16 = 246 Hz => 4 mS) // Take overflow of c1 and use an input to c2 // Overflow of c2 is the slow clock wire c1over; wire slow_clock; reg [7:0] c1v; reg [7:0] c2v; counter8 c1(clock, 0, c1v, c1over); counter8 c2(c1over, 0, c2v, slow_clock); // Four bits to keep track of last button values // Set output value if 4 in a row match reg [3:0] history; always @ (posedge slow_clock) begin history = {history[2:0], button}; // Shift previous values if (history == 4'b0000) value <= 1'b0; else if (history == 4'b1111) value <= 1'b1; end endmodule // Simple 8-bit counter with synchronous reset and overflow module counter8 ( input clock, input reset, output [7:0] count, output overflow ); // Be clear these are registers reg [7:0] count; reg overflow; always @ (posedge clock or posedge reset) begin if (reset) count <= 8'h00; // Set to zero else begin count <= count + 1; // Overflow is set when counter is resetting to zero overflow <= (count == 8'hFF); end end endmodule