Загрузка данных


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 04.05.2026 20:06:49
// Design Name: 
// Module Name: debouncer
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module debouncer #(
    parameter CLK_FREQ = 50_000_000,
    parameter WAIT_TIME_MS = 10
)(
input clk_i,
input nrst_i,
input btn_i,
output reg btn_o
) ;

// Вычисление лимита счетчика
localparam CNT_MAX = (CLK_FREQ / 1000) * WAIT_TIME_MS;
localparam integer WIDTH = $clog2 (CNT_MAX);

reg[WIDTH-1:0] count;
reg [1:0] sync_reg;
reg btn_stable;

// 1. Двухстадийный синхронизатор для устранения метастабильности
always @(posedge clk_i or negedge nrst_i) begin
     if (!nrst_i)
        sync_reg <= 2'b00;
     else
        sync_reg <= {sync_reg[0], btn_i};
end

wire btn_sync = sync_reg[1];

// 2. Счетчик стабильности уровня сигнала
always @(posedge clk_i or negedge nrst_i) begin
    if (!nrst_i) begin
        count <= 0;
        btn_stable <= 1'b0;
    end else begin
        // Если текущий стабильный уровень не совпадает со входом
        if (btn_sync != btn_stable) begin
            if (count < CNT_MAX - 1) begin
                count <= count + 1'b1;
            end else begin
                // Бремя вышло, обновляем стабильное состояние
                btn_stable <= btn_sync;
                count <= 0;
            end
        end else begin
            // Входной сигнал совпадает со стабильным, сбрасываем счетчик
            count <= 0;
        end
    end
end

// 3. Выходной регистр
always @(posedge clk_i or negedge nrst_i) begin
    if (!nrst_i)
        btn_o <= 1'b0;
    else
    btn_o <= btn_stable;
end


endmodule
module digital_lock(
    input clk_i,
    input nrst_i,
    input  btn0_i,
    input  btn1_i,
    output reg [3:0] leds
    ) ;
    
// Детектор переднего фронта с кнопок (импульс в 1 такт при нажатии)
    reg b0_r, b1_r;
    wire p0, p1;
    
    always @(posedge clk_i) begin
        b0_r <= btn0_i;
        b1_r <= btn1_i;
    end
    assign p0 = (btn0_i && !b0_r); // Нажата кнопка 0
    assign p1 = (btn1_i && !b1_r); // Нажата кнопка 1
    
    //Состояния конечного автомата (5 состояний)
    localparam S_RESET = 3'b000, // ничего не введено
               S_GOT_1 = 3'b001, // Ввели '1'
               S_GOT_10 = 3'b010, // Ввели '10'
               S_GOT_101= 3'b011, // Ввели "101"
               S_OPEN= 3'b100; // Ввели '1010' (Замок открыт)

reg [2:0] state, next_state;

// Блок 1: Регистр текущего состояния
always @(posedge clk_i or negedge nrst_i) begin
    if (!nrst_i) state <= S_RESET;
    else state <= next_state;
end

//Блок 2: Логика переходов (для кода 1-0-1-0)
    always @(*) begin
        next_state = state;
        case (state)
            S_RESET: begin
                if (p1)    next_state = S_GOT_1; // Первая верная цифра "1"
                else if (p0) next_state = S_RESET; // Ошибка, ждем дальше
            end
            S_GOT_1: begin
                if (p0)      next_state = S_GOT_10; // Вторая верная цифра 101
                else if (p1) next_state = S_GOT_1; // Ошибка, но эта '1' начинаетновый код
            end
            S_GOT_10: begin
                if (p1)     next_state = S_GOT_101;// Третья верная цифра '1'
                else if (p0) next_state = S_RESET; // Полный сброс (00 не подходит)
            end
            S_GOT_101: begin
                if (p0)     next_state = S_OPEN; // Четвертая верная цифра '0" ->откРыто!
                else if (p1) next_state = S_GOT_1; // Ошибка, но эта '1' начинает новый код
            end
            S_OPEN: begin
                if (p0 || p1) next_state = S_RESET; // Cброс по нажатию любой кнопки
            end
            default: next_state = S_RESET;
    endcase
end

    // Блок 3: Логика выходов
    always @(*) begin
        case (state)
            S_RESET:   leds = 4'b0000; // Все выключены:
            S_GOT_1:   leds = 4'b0001; // Горит 1-й светодиод
            S_GOT_10:  leds = 4'b0011; // Горят 1-й и 2-й
            S_GOT_101: leds = 4'b0111; // Горят 1, 2 и 3-й
            S_OPEN:    leds = 4'b1111; // Горят все 4 светодиода
            default:   leds = 4'b0000;
        endcase
    end
endmodule