From bbd177ba0b312a38729892f60c0b1ec82c28af54 Mon Sep 17 00:00:00 2001 From: irobo Date: Wed, 13 May 2026 17:32:27 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D0=BD=D0=B4=D0=B5=D0=BA=D1=81=20=D1=87?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=BE=D1=82=D1=8B:=200..5=20=E2=86=92=200,10?= =?UTF-8?q?,20,30,40,50=20=D0=93=D1=86=20english?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blink.v | 159 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 81 insertions(+), 78 deletions(-) diff --git a/blink.v b/blink.v index db866c1..ac81a8f 100644 --- a/blink.v +++ b/blink.v @@ -1,4 +1,5 @@ module blink #( + // Input clock frequency in Hz parameter integer F_CLK = 50_000_000 // 50 MHz )( input wire clk, @@ -7,94 +8,96 @@ module blink #( 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; + //--------------------------------------------------------- + // Step duration: + // - for 0 Hz : 8 s + // - for others : 4 s + //--------------------------------------------------------- + localparam integer STEP_4SEC_MAX = (F_CLK * 4) - 1; + localparam integer STEP_8SEC_MAX = (F_CLK * 8) - 1; -reg [31:0] sec_cnt = 0; + // Step timer counter + reg [31:0] step_cnt = 32'd0; -// Индекс частоты: 0..5 → 0,10,20,30,40,50 Гц -reg [2:0] freq_idx = 0; -reg [2:0] freq_idx_prev = 0; // для детекта входа в 0 Гц + // Frequency index: 0..5 → 0,10,20,30,40,50 Hz + reg [2:0] freq_idx = 3'd0; -// Текущая половина периода в тактах -reg [31:0] max_count = 32'd0; + // Half-period counter and current half-period length in clock cycles + reg [31:0] blink_cnt = 32'd0; + reg [31:0] max_count = 32'd0; -// Базовый сигнал (до инверсий на выходах) -reg led_base = 1'b0; + // Base LED signal (before output inversions) + 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; + //--------------------------------------------------------- + // Function to calculate half-period in clock cycles + //--------------------------------------------------------- + function [31:0] calc_max_count; + input [2:0] idx; + integer f; + begin + // Frequency in Hz: 0, 10, 20, 30, 40, 50 + f = idx * 10; + if (f == 0) begin + // Special case: 0 Hz → no blinking + calc_max_count = 32'd0; end else begin - if (cnt >= max_count) begin - cnt <= 0; - led_base <= ~led_base; + // Half-period: F_CLK / (2 * f) + calc_max_count = (F_CLK / (2 * f)) - 1; + end + end + endfunction + + //--------------------------------------------------------- + // Main process: step timing, frequency selection, + // blink generation + //--------------------------------------------------------- + always @(posedge clk) begin + //----------------------------------------------------- + // Step timer: change frequency every 4 or 8 seconds + //----------------------------------------------------- + if (step_cnt >= (freq_idx == 3'd0 ? STEP_8SEC_MAX : STEP_4SEC_MAX)) begin + step_cnt <= 32'd0; + + // Cycle through 0→1→2→3→4→5→0... + if (freq_idx == 3'd5) + freq_idx <= 3'd0; + else + freq_idx <= freq_idx + 3'd1; + end else begin + step_cnt <= step_cnt + 32'd1; + end + + //----------------------------------------------------- + // Recalculate half-period for current frequency + //----------------------------------------------------- + max_count <= calc_max_count(freq_idx); + + //----------------------------------------------------- + // Blink generation + //----------------------------------------------------- + if (max_count == 32'd0) begin + // 0 Hz: hold current state, no blinking + blink_cnt <= 32'd0; + // led_base keeps its last value + end else begin + if (blink_cnt >= max_count) begin + blink_cnt <= 32'd0; + led_base <= ~led_base; end else begin - cnt <= cnt + 1; + blink_cnt <= blink_cnt + 32'd1; end end end -end -//------------------------------------------------------------- -// Выходы: -// led = инверсия базового, -// pin = как led, -// pin_10 = инверсия pin -//------------------------------------------------------------- -assign led = ~led_base; -assign pin = led; -assign pin_10 = pin; + //--------------------------------------------------------- + // Outputs: + // led = inverted base signal + // pin = same as led + // pin_10 = inverted pin + //--------------------------------------------------------- + assign led = ~led_base; + assign pin = led; + assign pin_10 = ~pin; endmodule \ No newline at end of file