2015-11-13 4 views
3

Я пытаюсь закодировать реализацию контроллера/пути данных в Verilog, и я смущен тем, что вызовет нежелательную защелку. По существу, у меня есть обновление конечного автомата на часах отката. Этот конечный автомат отправляет 5 управляющих сигналов (loadSquare, loadDelta, addDelta и т. Д.) На путь данных, основанный на том, в каком состоянии находится устройство. Ниже приведен код для пути данных и контроллера.Почему оператор If вызывает запирание в verilog?

данных путь

//Control lines 
reg addSquare, addDelta, decDelta; 
reg loadSquare, loadDelta; 

//Input lines 
reg [8:0] square, delta; 

//Output register 
reg [7:0] outReg; 

always @(posedge clk) begin 
    if (loadSquare) 
    square = 9'h1; //used on initialization 

    if (loadDelta) 
    delta = 9'h3; //used on initialization 

    if (addSquare) 
    square = square + delta; 

    if (addDelta) 
    delta = delta + 2'h2; 

    if (decDelta) 
    outReg = (delta>>1) - 1; //used for output 
    else 
    outReg = Input; 
end 

Контроллер

//Output of module 
assign Output = outReg; 

//Finite State Machine 
always @(currentState) begin 
    case(currentState) 
     2'h0: begin  //initialize values, wait for start 
     {loadSquare, loadDelta} = 2'b11; 
     {addSquare, addDelta, decDelta} = 3'h0; 
    end 
     2'h1: begin 
     {loadSquare, loadDelta} = 2'b00; 
     {addSquare, addDelta, decDelta} = 3'b110; //add square and delta 
    end 
     2'h2: begin 
     {loadSquare, loadDelta} = 2'b00; 
     {addSquare, addDelta, decDelta} = 3'b001; //decrement delta, wait for reset 
    end 
     default: ; // unused 
    endcase 

//Next state logic implemented on negedge clk (not shown) 

Этот код генерирует следующие предупреждения в Xilinx:

WARNING:Xst:737 - Found 1-bit latch for signal <addDelta>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems. 
WARNING:Xst:737 - Found 1-bit latch for signal <decDelta>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems. 
WARNING:Xst:737 - Found 1-bit latch for signal <loadDelta>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems. 
WARNING:Xst:1294 - Latch <loadDelta> is equivalent to a wire in block <ModuleName>. 
WARNING:Xst:1294 - Latch <decDelta> is equivalent to a wire in block <ModuleName>. 
WARNING:Xst:1294 - Latch <addDelta> is equivalent to a wire in block <ModuleName>. 

Я понимаю, что неполной, если заявления вызывают защелки. Чтобы попытаться объяснить это, я пробовал две разные реализации, но они не удаляют предупреждения. Меня особенно смущает дело «decDelta», потому что я не понимаю, что я не учитываю в этом условном утверждении.

Try # 1

always @(posedge clk) begin 
    if (loadSquare) 
    square = 9'h1; 
    else 
    square = square; 

    if (loadDelta) 
    delta = 9'h3; 
    else 
    delta = delta; 

    //... and so on 

Try # 2

always @(posedge clk) begin 
    square = square; 
    delta = delta; 

    if (loadSquare) 
    square = 9'h1; 

    if (loadDelta) 
    delta = 9'h3; 

    //... and so on 

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

+1

Для 'always @ (posedge clk)' вы должны использовать '<=' неблокирующие назначения для правильной имитации триггера. – Morgan

+2

Можете ли вы показать, как управляется 'addDelta'/ – Morgan

+0

Убедитесь, что есть инструкция« else »для« if ». Задвижки создаются, если вы не укажете состояние сигнала при некоторых условиях. Поэтому не забудьте указать все случаи. – vipin

ответ

0

Защелка является основным элементом памяти, она открыта или закрыта, т.е. чувствительна к уровню. Триггер - это в основном два защелки, один из которых работает на инвертирующем сигнале включения, что делает его чувствительным к краю.

При использовании always @(posedge clk) вы подразумеваете триггер, который загружает значения данных на передний фронт clk. Замки не подразумеваются внутри этого процесса (always @(posedge clk)).

Как описано Sharvil111, защелки подразумеваются, когда вы оставили неопределенные состояния в комбинаторных разделах, то есть always @* процессов. Если какая-то вещь не определена в условном выражении, то она сохраняет свое значение. Сохранение значения - состояние, и поскольку комбинаторные секции не чувствительны к краю, вы вынудили инструмент вставить защелку.

Чтобы избежать этого полностью определить условный выход:

always @(currentState) begin 
case(currentState) 
    2'h0: begin  //initialize values, wait for start 
    {loadSquare, loadDelta} = 2'b11; 
    {addSquare, addDelta, decDelta} = 3'h0; 
end 
    2'h1: begin 
    {loadSquare, loadDelta} = 2'b00; 
    {addSquare, addDelta, decDelta} = 3'b110; //add square and delta 
end 
    2'h2: begin 
    {loadSquare, loadDelta} = 2'b00; 
    {addSquare, addDelta, decDelta} = 3'b001; //decrement delta, wait for reset 
end 
    default: begin 
    {loadSquare, loadDelta} = 2'b00; 
    {addSquare, addDelta, decDelta} = 3'b000; 
    end 
endcase 
1

Защелки Inferred, когда переменная придется сохранить свое прежнее значение, если оно не назначается значение в всегда блокировать. Защелка должна быть создана до магазина настоящая стоимость.

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

неполныйif-else заявление будет генерировать нежелательные защелки. Оператор if-else считается «неполным», если одно из условий не определено для всех возможных условий ввода. Аналогичным образом, незавершенный оператор case, который не имеет оператора default, также может вывести защелку.

полнойif-else утверждения относится к следующему Mux:

Mux

While и неполногоif-else относится к пути в обратной связи от выхода к входу, чтобы провести в предыдущее значение.Аналогично относится к заявлению case.

MuxLatch

Как правило, комбинационная петля следует избегать:

общего намерения комбинационной схемы является то, что выходным сигналом является функцией только входа и схема не должна содержать какие-либо внутреннее Состояние (т.е. память).

В противоречие, Verilog стандарт указывает, что переменная должна сохранять/держать его предыдущее значение если оно не присваивается значение в всегда блокироваться. Это основная причина создания защелки.

Чтобы избежать защелки, следующие пункты должны иметь в виду:

  • Включите все ветви оператора if или case.
  • Назначить значение каждый выходной сигнал в каждая ветка.

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

if (loadSquare) 
    square <= 9'h1; //used on initialization 
else 
    square <= 9'h0; // similar for all the variables 

Другой альтернативной является присвоение значения по умолчанию на каждом такте.

always @ (posedge clk) 
begin 
square <= 9'h0; // similar for all the variables 
if (loadSquare) 
    square <= 9'h1; //used on initialization 
end 

Side Примечание: Я использовал неблокирующие присваиваний заявления здесь, для правильного синтеза флип-флоп.

Для получения подробной информации о синтезе см. FPGA prototyping by Verilog examples by Pong P. Chu pdf. Также могут быть полезны this и this ссылки о создании защелки.

Изображение предоставлено doulous.com.

+0

Удаление регистра в каждом цикле, за исключением случаев, когда 'loadDelta' является высоким, не является предполагаемым поведением автора. Примечание: ошибка не вызвана чтением процесса, это вызвано процессом вождения для ex. 'AddDelta'. – Paebbels

+0

@ downvoter. С предельным уважением, я фокусирую свой ответ на линии. ** ... и я смущен тем, что вызовет нежелательную защелку. ** и методы пробного тестирования. Пожалуйста, не думайте об этом иначе. – sharvil111

+0

@Paebbels, я просто объясняю причину предупреждений и создания защелки во время синтеза. Это не имеет никакого отношения к логике loadDelta. Чтобы объяснить это, я использовал имена сигналов, предоставленные OP, тип псевдокода. Я согласен с тем, что предупреждения возникают во время ** вождения ** этих трех сигналов: «addDelta», «decDelta» и т. Д., Но сейчас мое внимание сосредоточено только на обобщенной причине предупреждений. – sharvil111

0

Защелки являются причиной логики конечного автомата. Следующий всегда блок чувствителен к currentState, а не к часам.Это не плохо, но требует некоторых дополнительных мер предосторожности, чтобы препятствовать защелкой создания:

  1. использовать в default случае или
  2. назначения использования по умолчанию ИЛИ
  3. использовать другой шаблон FSM

Здесь это ваш код с моими дополнениями с использованием заданий по умолчанию:

//Finite State Machine 
always @(currentState) begin 
    // default assignments 
    {loadSquare, loadDelta} = 2'b0; 
    {addSquare, addDelta, decDelta} = 3'h0;   

    case(currentState) 
     2'h0: begin  //initialize values, wait for start 
     {loadSquare, loadDelta} = 2'b11; 
     {addSquare, addDelta, decDelta} = 3'h0; 
     end 
     2'h1: begin 
     {loadSquare, loadDelta} = 2'b00; 
     {addSquare, addDelta, decDelta} = 3'b110; //add square and delta 
     end 
     2'h2: begin 
     {loadSquare, loadDelta} = 2'b00; 
     {addSquare, addDelta, decDelta} = 3'b001; //decrement delta, wait for reset 
     end 
     default: ; // unused 
    endcase 

//Next state logic implemented on negedge clk (not shown) 

Для получения дополнительной информации о создании защелок смотрите на ответ @ sharvil111. Он рассматривает эту тему более общим образом.

0

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

case(currentState) 
2'h0: begin  //initialize values, wait for start 
    {loadSquare, loadDelta} = 2'b11; 
    {addSquare, addDelta, decDelta} = 3'h0; 
end 
2'h1: begin 
    {loadSquare, loadDelta} = 2'b00; 
    {addSquare, addDelta, decDelta} = 3'b110; //add square and delta 
end 
2'h2: begin 
    {loadSquare, loadDelta} = 2'b00; 
    {addSquare, addDelta, decDelta} = 3'b001; //decrement delta, wait for reset 
end 
default: ; // unused // <-- not assigned so assumed keep; inferred latches 
endcase 
... 

Делать что-то вроде addSquare = addSquare; это еще Inferred защелки. addSquare (и все другие переменные) должны быть назначены константе, флопе (кросс-чувствительный триггер) или членам комбинационной функции констант и значений флопа.

Если вам действительно не нужно addSquare (и все другие переменные), то просто назначьте их константе в состоянии default.

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

always @(posedge clk) begin 
    ... 
    addSquare_keep <= addSquare; 
    ... 
end 
always @* begin 
    ... 
    case(currentState) 
    ... 
    default : begin 
    ... 
    addSquare = addSquare_keep; 
    ... 
    end 
    endcase 
    ... 
end 
Смежные вопросы