Регистрируйте приращения дважды в неблокирующем режиме всегда

Я хочу сделать повышающий счетчик с возможностью вывода (при высоком значении счетчик должен подсчитываться при каждом такте, в противном случае он сохраняет свое предыдущее значение). Чтобы добиться видимых результатов на моей плате Altera TerASIC, я использовал ее встроенный тактовый генератор и встроил в Verilog модуль делителя тактовой частоты, чтобы подать на мой повышающий счетчик тактовый сигнал с гораздо более подходящей частотой. Кроме того, я создал шестнадцатеричный модуль, который подключил к выходу моего обратного счетчика, чтобы иметь возможность видеть выходные значения в виде цифр. Проблема в том, что я не знаю, почему выходные данные увеличиваются на 2 за каждый такт (вместо 1, как ожидалось) при запуске проекта на плате TeraASIC. Я предоставляю весь код ниже, так как не знаю, откуда возникла проблема. Хотя я считаю, что с шестнадцатеричным модулем все в порядке. Проблема возникает либо внутри блока счетчика, либо внутри блока делителя. Кроме того, я сделал небольшой тестовый стенд, результаты которого необычны, поскольку подтверждают, что схема работает нормально. В нижней части этого поста я подробно рассказал о тестовом стенде. Тем не менее, интересно, что если я заменю else if из счетчика на простое else, которое не учитывает сигналы en и d, я получу полностью функциональную конструкцию, простой повышающий счетчик, который увеличивает свое значение после каждого фронта тактовой частоты. . Я не знаю, почему это происходит. Возможно, настоящая проблема скрыта именно там. Я поместил комментарий в эту область кода, чтобы сделать ее более заметной.

module counter(
    input clk,
    input rst_b,
    input en,
    input [2:0] d,
    output [6:0] digit
);

wire clk_d;
reg [2:0] q;

divider i0(.clk(clk),.rst_b(rst_b),.clk_d(clk_d));
decoder i1(.binary(q),.digit(digit));

always @(posedge clk_d, negedge rst_b) begin
    if (rst_b == 1'b0)
        q <= 3'b000;
    else if (en)//when it was only else q<=q+en; it went fine...why???
        if (q == d)
            q <= 3'b000;
        else
            q <= q + en;//increment by 2 instead of 1
end

endmodule


module divider(
    input clk,
    input rst_b,
    output clk_d
);

reg [24:0] q;

always @(posedge clk) begin
    if (rst_b == 1'b0)
        q <= 25'b0;
    else
        q <= q-1;
end

assign clk_d = (q == 25'b0);

endmodule


module decoder(
    input [2:0] binary,
    output reg [6:0] digit
);

always @ * begin
    case (binary)
        4'h0: digit = ~7'b0111111;
        4'h1: digit = ~7'b0000110;
        4'h2: digit = ~7'b1011011;
        4'h3: digit = ~7'b1001111;
        4'h4: digit = ~7'b1100110;
        4'h5: digit = ~7'b1101101;
        4'h6: digit = ~7'b1111101;
        4'h7: digit = ~7'b0000111;
        default : digit = ~7'b1110001;
    endcase
end

endmodule

У меня есть небольшой тестовый стенд, который поразительно доказывает, что, по крайней мере теоретически, мой модуль работает нормально:

module counter_tb;

reg clk, rst_b, en;
reg [2:0] d;
wire [6:0] digit;

counter i0( .clk(clk),
            .rst_b(rst_b),
            .en(en),
            .d(d),
            .digit(digit)
);

always begin
    #1 clk = ~clk;
end

initial begin
    clk = 1'b0;
    en = 1'b1;
    d = 3'b111;
    rst_b = 1'b0;
    #3 rst_b = 1'b1;
end
    
endmodule
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не знаю точно, в чем ваша проблема или какое решение, однако вы используете практику проектирования, которая, как правило, не работает в потоке синтеза (нацеленном на аппаратное обеспечение) для создания часов. Если это работает в одной сборке, то может не работать в следующей. Небольшая дополнительная задержка (например, добавление разрешения) приведет к совершенно другим результатам в аппаратном обеспечении.

Эта практика обманчива, потому что вы можете написать что-то, что в моделировании будет вести себя так, как вы хотите, но не будет вести себя так, как ожидается, в рабочем процессе синтеза/аппаратного обеспечения. Симулятор Verilog обычно не моделирует задержки (моделирование на основе задержек возможно, но все равно не решает проблемы), поэтому необходимо использовать определенные передовые методы проектирования, чтобы результаты аппаратного обеспечения согласовывались с моделированием.

Как правило, вы не можете создавать часы и использовать их в качестве часов для других триггеров, используя простые делители триггеров в физической FPGA. Есть два надежных варианта получения поведения, связанного с генерацией более медленных часов.

  1. Создайте разрешения медленных часов, используя счетчик в качестве делителя, а затем используйте их в качестве разрешений.
  2. Используйте части, встроенные в IP-блоки делителя тактового сигнала MMCM/PLL, чтобы создать более медленный тактовый сигнал.

Эта ссылка объясняет больше и хорошо написана, я не мог бы объяснить это лучше
Делители часов с использованием триггеров в RTL на FPGA – большое НЕТ!
без написания статьи.

Это будет отдельный и новый вопрос и ответ
«Как мне создать делитель тактовой частоты в FPGA, который может использовать аппаратное обеспечение в рабочих процессах синтеза»

Я бы избавился от триггерного делителя assign clk_d = (q == 25'b0); и связанной с ним логики и использовал одно из двух решений, которые я упомянул и которые упомянуты по предоставленной ссылке.


Кроме того, если вы развертываете код RTL в лаборатории без моделирования с помощью тестового стенда, вы часто будете видеть черный ящик с надписью «это не работает».

Очень хороший подход. Действительно, как я добавил в своем последнем редактировании, я столкнулся с таким поведением только при реализации на моей физической плате, поскольку тестовый стенд выглядел нормально.

pauk 21.04.2024 21:21

Я бы использовал подход с включением тактовой частоты, если только вам не нравится углубляться в работу с поставщиками, встроенными в IP.

Mikef 21.04.2024 21:29

Другие вопросы по теме