Загрузка данных
`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