Quartus_blink/blink.v

100 lines
3.2 KiB
Verilog
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

module blink #(
parameter integer F_CLK = 50_000_000 // 50 MHz
)(
input wire clk,
output wire led,
output wire pin,
output wire pin_10
);
//-------------------------------------------------------------
// Длительность шага: 0 Гц = 8с, остальные = 4с
//-------------------------------------------------------------
localparam integer STEP_4SEC_MAX = (F_CLK * 4) - 1;
localparam integer STEP_8SEC_MAX = (F_CLK * 8) - 1;
reg [31:0] sec_cnt = 0;
// Индекс частоты: 0..5 → 0,10,20,30,40,50 Гц
reg [2:0] freq_idx = 0;
reg [2:0] freq_idx_prev = 0; // для детекта входа в 0 Гц
// Текущая половина периода в тактах
reg [31:0] max_count = 32'd0;
// Базовый сигнал (до инверсий на выходах)
reg led_base = 1'b0;
//-------------------------------------------------------------
// Функция пересчёта max_count по freq_idx
//-------------------------------------------------------------
function [31:0] calc_max_count;
input [2:0] idx;
integer f;
begin
f = idx * 10; // 0,10,20,...,50 Гц
if (f == 0) begin
calc_max_count = 32'd0; // особый случай: 0 Гц
end else begin
calc_max_count = (F_CLK / (2 * f)) - 1;
end
end
endfunction
//-------------------------------------------------------------
// Счётчик мигания + смена частоты
//-------------------------------------------------------------
reg [31:0] cnt = 0;
always @(posedge clk) begin
// Смена частоты по таймеру
if (sec_cnt >= (freq_idx == 3'd0 ? STEP_8SEC_MAX : STEP_4SEC_MAX)) begin
sec_cnt <= 0;
// сохраняем предыдущий индекс
freq_idx_prev <= freq_idx;
// Цикл по частотам 0→10→20→30→40→50→0...
if (freq_idx == 3'd5)
freq_idx <= 0;
else
freq_idx <= freq_idx + 1;
max_count <= calc_max_count(freq_idx == 3'd5 ? 0 : freq_idx + 1);
end else begin
sec_cnt <= sec_cnt + 1;
end
// Одноразовый импульс при входе в режим 0 Гц:
// когда freq_idx стало 0, а раньше было не 0
if ((freq_idx == 3'd0) && (freq_idx_prev != 3'd0)) begin
// один "щелчок": инвертируем led_base один раз
led_base <= ~led_base;
cnt <= 0;
end else begin
// обычное мигание для частот != 0 Гц
if (max_count == 0) begin
// 0 Гц: дальше не мигаем, состояние фиксировано
cnt <= 0;
end else begin
if (cnt >= max_count) begin
cnt <= 0;
led_base <= ~led_base;
end else begin
cnt <= cnt + 1;
end
end
end
end
//-------------------------------------------------------------
// Выходы:
// led = инверсия базового,
// pin = как led,
// pin_10 = инверсия pin
//-------------------------------------------------------------
assign led = ~led_base;
assign pin = led;
assign pin_10 = pin;
endmodule