Мой профессор смотрел на этот код добрых 10 минут, но не смог найти проблему. Итак, я надеюсь, что свежий взгляд увидит то, что мы оба упустили. Как всегда, я буду благодарен за любые подсказки, которые вы можете предоставить.
Контекст: модуль, который считает от FFF до 000, а затем повторяется.
Проблема: только самые низкие 2 отображают уменьшение, пропуская несколько чисел за раз, а затем возвращаясь к FF в, казалось бы, случайной точке.
Предположения: 1. Драйвер SevenSegment работает правильно. Он был проверен вручную и будет отображать присвоенное ему шестнадцатеричное число 2. Модуль ClockDivider работает по назначению. Обратный отсчет уменьшается каждую 1 секунду, как и должно (CLOCK_50 = 50 МГц)
Возможный совет: Verilog предупреждает, что «cd» является предполагаемой защелкой и сохраняет свое значение через один или несколько путей в блоке «always».
module ClockDivider( input CLOCK_50, output reg[ 31:0] count );
parameter clockDivisor = 50_000_000;
always @( posedge CLOCK_50 )
if ( count == 0)
count <= clockDivisor;
else
count <= count - 1;
endmodule
module Test (
//////////// CLOCK //////////
input CLOCK_50,
//////////// SEG7 //////////
output [6:0] HEX0,
output [6:0] HEX1,
output [6:0] HEX2
);
//ClockDivider Output
wire [31:0] cout;
reg [11:0] cd;
ClockDivider a( CLOCK_50, cout);
always @(cout)
begin
if (cout == 32'h0)
if (cd == 12'h0)
cd <= 12'hFFF;
else
cd <= (cd - 12'h001);
end
SevenSegment C2( cd[11:8], 1'b0, HEX2 );
SevenSegment C1( cd[7:4], 1'b0, HEX1 );
SevenSegment C0( cd[3:0], 1'b0, HEX0 );
endmodule
Лично у меня всегда были проблемы с @(cout) , которые могут быть ненадежными.
Я бы всегда использовал всегда @(posedge CLOCK_50) . На мой взгляд, таким образом вам гарантирован должный результат...
РЕДАКТИРОВАТЬ: добавлен более четкий код для вышеуказанного предложения
always @(cout) -> always @(posedge CLOCK_50)
cout должен изменяться только с положительным фронтом часов в теории (или в коде), но то, что на самом деле происходит, может быть другим. Ваш временной отчет расскажет вам о времени установки и резерве — и это может быть вашей проблемой. измените свою логику на все «синхронные», и я готов поспорить, что это сработает.
Кроме того, рекомендуется избавиться от предполагаемой защелки. все, что для этого потребуется, это оператор else:
if (cout == 32'h0)
if (cd == 12'h0)
cd <= 12'hFFF;
else
cd <= (cd - 12'h001);
else
cd <= cd;
РЕДАКТИРОВАТЬ: предлагаемый рабочий код
module ClockDivider(input CLOCK_50,
output reg[ 0:0] en
);
parameter clockDivisor = 50_000_000;
reg [31:0] i;
always @( posedge CLOCK_50 ) begin
if ( i == clockDivisor ) begin
en <= 1;
i <= 0;
end
else begin
en <= 0;
i <= i + 32'b1;
end
end
endmodule
//1Hz clock output
wire [0:0] en;
//Holds the countdown value FFF-000
reg [11:0] cd;
ClockDivider CLOCK_1Hz( CLOCK_50, en);
always @(posedge CLOCK_50)
if (en) begin
if (cd == 12'h0)
cd <= 12'hFFF;
else
cd <= (cd - 12'h001);
end
else
cd <= cd;
end
else cd <= cd;
по-прежнему создает защелку; все, что вы сделали, это сделали это явным, а не неявным. Вообще следует избегать комбинаторных защелок, созданных таким образом.always @(<xxx>)
что рекомендуете.Благодаря ThePhoton и johhnymopo я смог найти решение. Решение состояло в том, чтобы ClockDivisor сам действовал как более медленные часы. Код становится:
module ClockDivider( input CLOCK_50, output reg[ 0:0] count );
parameter clockDivisor = 50_000_000;
reg [31:0] i;
always @( posedge CLOCK_50 )
begin
i <= i + 32'b1;
if ( i == clockDivisor )
begin
count <= 1;
i <= 0;
end
else
count <= 0;
end
endmodule
В данном случае это часы с частотой 1 Гц. Затем можно запустить декремент обратного отсчета, используя положение этих более медленных часов:
//1Hz clock output
wire [0:0] slowClock;
//Holds the countdown value FFF-000
reg [11:0] cd;
ClockDivider CLOCK_1Hz( CLOCK_50, slowClock);
always @(posedge slowClock)
begin
if (cd == 12'h0)
cd <= 12'hFFF;
else
cd <= (cd - 12'h001);
end
cd
изменения происходили бы один раз в секунду, но по-прежнему основывались бы на тактовой частоте 50 МГц и, следовательно, все еще были бы защелками, но это кажется странным. Я по-прежнему рекомендую использовать общие часы для всей логики, когда это возможно.
Фотон
Фотон
cout
список чувствительности, но он никогда не появляется в правой части любого из назначений под ним. Итак, что может сделать инструмент, кроме того, что вы хотите использоватьcout
в качестве тактового сигнала для блока.меридиан