diff --git a/blink.v b/blink.v index b269117..db866c1 100644 --- a/blink.v +++ b/blink.v @@ -1,55 +1,100 @@ module blink #( - // Выбор частоты мигания (F_BLINK), Гц: - // 1 -> 1 - // 2.5 -> 25 (см. ниже, делим на 10) - // 5 -> 5 - // 10 -> 10 - parameter integer MODE = 4 // по умолчанию 1 Гц + parameter integer F_CLK = 50_000_000 // 50 MHz )( - input wire clk, // 50 MHz - output reg led, - output reg pin, - output reg pin_10 + input wire clk, + output wire led, + output wire pin, + output wire pin_10 ); -localparam integer F_CLK = 50_000_000; +//------------------------------------------------------------- +// Длительность шага: 0 Гц = 8с, остальные = 4с +//------------------------------------------------------------- +localparam integer STEP_4SEC_MAX = (F_CLK * 4) - 1; +localparam integer STEP_8SEC_MAX = (F_CLK * 8) - 1; -// Предрасчитанные MAX_COUNT для половины периода: -// -// 1 Гц: T=1 c → T/2=0.5 c → 25_000_000 -// 2.5 Гц: T=0.4 c → T/2=0.2 c → 10_000_000 -// 5 Гц: T=0.2 c → T/2=0.1 c → 5_000_000 -// 10 Гц: T=0.1 c → T/2=0.05 c → 2_500_000 +reg [31:0] sec_cnt = 0; -localparam integer MAX_1HZ = 25_000_000 - 1; -localparam integer MAX_2_5HZ = 10_000_000 - 1; -localparam integer MAX_5HZ = 5_000_000 - 1; -localparam integer MAX_10HZ = 2_500_000 - 1; +// Индекс частоты: 0..5 → 0,10,20,30,40,50 Гц +reg [2:0] freq_idx = 0; +reg [2:0] freq_idx_prev = 0; // для детекта входа в 0 Гц -// Выбор MAX_COUNT по MODE -// MODE: -// 1 -> 1 Гц -// 2 -> 2.5 Гц -// 3 -> 5 Гц -// 4 -> 10 Гц -localparam integer MAX_COUNT = - (MODE == 1) ? MAX_1HZ : - (MODE == 2) ? MAX_2_5HZ : - (MODE == 3) ? MAX_5HZ : - (MODE == 4) ? MAX_10HZ : - MAX_1HZ; // по умолчанию 1 Гц +// Текущая половина периода в тактах +reg [31:0] max_count = 32'd0; -reg [25:0] cnt; // хватает до > 33 млн (2^25 = 33_554_432) +// Базовый сигнал (до инверсий на выходах) +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 (cnt >= MAX_COUNT) begin - cnt <= 0; - led <= ~led; - pin <= led; - pin_10 <= led; + // Смена частоты по таймеру + 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 - cnt <= cnt + 1; + 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 \ No newline at end of file