`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Elektronska brava sa sifrom - PYNQ-Z2 verzija // // Korisceni pinovi na ploci: // button0, button1, button2, button3 -> PYNQ-Z2 push buttons // led0, led1, led2, led3 -> PYNQ-Z2 LEDs // // Tacna sifra: // button0 -> button1 -> button2 -> button3 // // Reset sistema: // press button3 // // Znacenje LED dioda: // led0 = prvi korak sifre prihvacen // led1 = drugi korak sifre prihvacen // led2 = treci korak sifre prihvacen // led3 = pristup dozvoljen / sistem zakljucan ////////////////////////////////////////////////////////////////////////////////// `timescale 1ns / 1ps module electronic_lock_pynqz2( input wire clk, input wire button0, input wire button1, input wire button2, input wire button3, output reg led0, output reg led1, output reg led2, output reg led3 ); localparam integer CLK_FREQ = 125_000_000; localparam integer DEBOUNCE_LIMIT = 2_500_000; localparam integer LOCK_TIME = 5; localparam S_IDLE = 3'd0; localparam S_KEY1 = 3'd1; localparam S_KEY2 = 3'd2; localparam S_KEY3 = 3'd3; localparam S_GRANTED = 3'd4; localparam S_ERROR = 3'd5; localparam S_LOCKED = 3'd6; reg [2:0] state = S_IDLE; reg [1:0] attempts = 2'd0; reg [3:0] btn_sync_0 = 4'b0000; reg [3:0] btn_sync_1 = 4'b0000; wire [3:0] buttons_raw; assign buttons_raw = {button3, button2, button1, button0}; always @(posedge clk) begin btn_sync_0 <= buttons_raw; btn_sync_1 <= btn_sync_0; end reg [3:0] btn_last = 4'b0000; reg [3:0] btn_stable = 4'b0000; reg [21:0] debounce_cnt = 0; reg key_event = 1'b0; reg [1:0] key_code = 2'd0; always @(posedge clk) begin key_event <= 1'b0; if (btn_sync_1 != btn_last) begin btn_last <= btn_sync_1; debounce_cnt <= 0; end else begin if (debounce_cnt < DEBOUNCE_LIMIT) begin debounce_cnt <= debounce_cnt + 1; end else begin if (btn_stable != btn_sync_1) begin btn_stable <= btn_sync_1; if (btn_sync_1 != 4'b0000) begin key_event <= 1'b1; if (btn_sync_1[0]) key_code <= 2'd0; else if (btn_sync_1[1]) key_code <= 2'd1; else if (btn_sync_1[2]) key_code <= 2'd2; else if (btn_sync_1[3]) key_code <= 2'd3; end end end end end reg [27:0] sec_cnt = 0; reg one_sec_tick = 1'b0; always @(posedge clk) begin one_sec_tick <= 1'b0; if (sec_cnt == CLK_FREQ - 1) begin sec_cnt <= 0; one_sec_tick <= 1'b1; end else begin sec_cnt <= sec_cnt + 1; end end reg [3:0] lock_seconds = 0; reg blink = 1'b0; always @(posedge clk) begin if (one_sec_tick) begin blink <= ~blink; end end always @(posedge clk) begin case (state) S_IDLE: begin if (key_event) begin if (key_code == 2'd0) state <= S_KEY1; else state <= S_ERROR; end end S_KEY1: begin if (key_event) begin if (key_code == 2'd1) state <= S_KEY2; else state <= S_ERROR; end end S_KEY2: begin if (key_event) begin if (key_code == 2'd2) state <= S_KEY3; else state <= S_ERROR; end end S_KEY3: begin if (key_event) begin if (key_code == 2'd3) begin state <= S_GRANTED; attempts <= 0; lock_seconds <= 0; end else begin state <= S_ERROR; end end end // Kada je brava otvorena, ponovni pritisak na button3 vraca sistem na pocetak S_GRANTED: begin if (key_event && key_code == 2'd3) begin state <= S_IDLE; attempts <= 0; lock_seconds <= 0; end else begin state <= S_GRANTED; end end S_ERROR: begin if (attempts == 2'd2) begin attempts <= attempts + 1; state <= S_LOCKED; lock_seconds <= 0; end else begin attempts <= attempts + 1; state <= S_IDLE; end end S_LOCKED: begin if (one_sec_tick) begin if (lock_seconds == LOCK_TIME - 1) begin lock_seconds <= 0; attempts <= 0; state <= S_IDLE; end else begin lock_seconds <= lock_seconds + 1; end end end default: begin state <= S_IDLE; end endcase end always @(*) begin led0 = 1'b0; led1 = 1'b0; led2 = 1'b0; led3 = 1'b0; case (state) S_IDLE: begin led0 = attempts[0]; led1 = attempts[1]; end S_KEY1: begin led0 = 1'b1; end S_KEY2: begin led0 = 1'b1; led1 = 1'b1; end S_KEY3: begin led0 = 1'b1; led1 = 1'b1; led2 = 1'b1; end S_GRANTED: begin led0 = 1'b1; led1 = 1'b1; led2 = 1'b1; led3 = 1'b1; end S_ERROR: begin led3 = 1'b1; end S_LOCKED: begin led0 = blink; led1 = blink; led2 = blink; led3 = blink; end default: begin led0 = 1'b0; led1 = 1'b0; led2 = 1'b0; led3 = 1'b0; end endcase end endmodule