Verilog: установка постоянного значения на часах даже - PullRequest
2 голосов
/ 14 декабря 2011

Я новичок в Verilog, поэтому этот вопрос может быть довольно глупым.

Что я пытаюсь: у меня есть компонент, который имеет clk, 8-битный вход и 8-битный выход.Что он должен сделать, это:

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

Что я пробовал до сих пор:

always @(negedge clk)
    _ledOut <= 0;

always @(posedge clk)
    _ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];

Это говорит о том, что он не можетразрешить несколько константных драйверов для net _ledOut.

Однако, если объединить это в всегда @ (negedge clk, posedge clk), я не могу проверить оба условия.

Так что япопытался создать только один всегда @ (clk) блок, а затем использовал оператор if:

always @(clk) begin
    if(clk == 0)
        _ledOut <= 0;
    else if(clk == 1)
        _ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];
end

Но это не просто включило событие clk.Во время высокой фазы часов он связывает _ledOut со ledIn, так что изменения в ledIn также влияют на _ledOut.Что я здесь не так делаю?

С уважением, Майкл

Ответы [ 4 ]

5 голосов
/ 15 декабря 2011

Это говорит мне, что он не может разрешить несколько постоянных драйверов для сети _ledOut.

Для синтеза нельзя назначать типы регистров из нескольких блоков всегда.

Однако, собирая это вместе всегда @ (negedge clk, posedge clk) говорит, что не может проверить оба условия.

Это по существу описывает регистр DDR. Хотя многие устройства FPGA имеют их, они, как правило, не могут быть синтезированы. Xilinx использует примитивы ODDR2 и IDDR2, если вам действительно нужна эта функциональность.

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

Если это все, что вам нужно, вы можете использовать D-триггер с логическим вентилем AND на выходе. Триггер будет проверять ledIn на каждом переднем фронте clk, а вентиль AND будет маскировать выходной сигнал всякий раз, когда часы равны нулю. Это не идеально, так как вы обычно не хотите, чтобы часы касались непоследовательной логики, но избегание этого, вероятно, означало бы изменение ваших требований.

Как указывалось в инструментарии, код, который вы разместили, будет работать, но вы должны понимать, что код будет синтезироваться в мультиплексор, управляемый clk.

1 голос
/ 15 декабря 2011

Хорошо, вот мое рабочее решение.Возможно, это не лучший код verilog, который вы когда-либо видели.;) Это, однако, мое первое, что я делаю с ним, как проект в моем университете.Так что, пока он делает то, что я хочу, это большой успех для меня!;)

Вот код, который я использовал сейчас, благодаря Adam12:

parameter RowSize = 8;

input clk;
input [RowSize-1:0] ledIn;
output [RowSize-1:0] ledOut;

reg[RowSize-1:0] _ledOut;
assign ledOut = _ledOut & {RowSize{clk}};

always @(posedge clk) begin
    _ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];
end
1 голос
/ 14 декабря 2011

Рассмотрим следующий стимул:

module tb;

parameter RowSize = 8;
reg clk;
reg [7:0] ledIn, _ledOut;

always @(clk) begin
    if(clk == 0)
        _ledOut <= 0;
    else if(clk == 1)
        _ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];
end

initial begin
    $monitor($time, " clk=%b ledIn=%h _ledOut=%h", clk, ledIn, _ledOut);
    ledIn = 0;
    #22 ledIn = 8'h55;
    #20 $finish;
end

always begin
    #5 clk <= 0;
    #5 clk <= 1;
end

endmodule

Он производит такой вывод:

               0 clk=x ledIn=00 _ledOut=xx
               5 clk=0 ledIn=00 _ledOut=00
              10 clk=1 ledIn=00 _ledOut=00
              15 clk=0 ledIn=00 _ledOut=00
              20 clk=1 ledIn=00 _ledOut=00
              22 clk=1 ledIn=55 _ledOut=00
              25 clk=0 ledIn=55 _ledOut=00
              30 clk=1 ledIn=55 _ledOut=55
              35 clk=0 ledIn=55 _ledOut=00
              40 clk=1 ledIn=55 _ledOut=55

Обратите внимание, что в момент 22, когда изменяется ledIn, выход _ledOut не изменяется. _ledOut изменяется только на следующей стадии clk в момент 30. Следовательно, решение always @(clk) делает то, что вам нужно: выходной сигнал изменяется только на границе часов, как вы указали.

0 голосов
/ 06 марта 2019

Это довольно необычный вопрос, и поэтому я советую вам дать больше информации о том, чего вы на самом деле пытаетесь достичь, так как это может сильно повлиять на производительность синхронизации и ограничения синхронизации, если это нацелено на FPGA.Синтез уже упоминался, но во что вы будете направлять синхронизированный выход?Если это пин-пад, то вы должны прочитать буферы DDR pad в спецификациях устройства и сделать вывод о конкретном примитиве, чтобы иметь возможность управлять сигналом DDR.

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

Ответы выше для вывода регистра с комбинаторным мультиплексором, принудительно установленным на выходе, интересны, но все, что вы вводите в это, будет иметь дело с неуклюжими условиями установки / удержания, а если на кристалле, будет толькоВ любом случае, выборка одного края является избыточной.

...