为什么 If 语句会导致 verilog 中的锁存?

Ant*_*ony 5 verilog fpga xilinx

我正在尝试在 Verilog 中编写控制器/数据路径实现,但我对什么会导致不需要的锁存感到困惑。本质上,我有一个在 negedge 时钟上更新的状态机。该状态机根据机器所处的状态向数据路径发送 5 个控制信号(loadSquare、loadDelta、addDelta 等)。数据路径和控制器的代码如下所示。

数据路径

//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
Run Code Online (Sandbox Code Playgroud)

控制器

//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)
Run Code Online (Sandbox Code Playgroud)

此代码在 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>.
Run Code Online (Sandbox Code Playgroud)

我知道不完整的 if 语句会导致锁存。为了尝试解决这个问题,我尝试了两种不同的实现,但它们没有删除警告。我对“decDelta”的情况特别困惑,因为我不明白我在这个条件语句中没有考虑到什么。

尝试#1

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

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

  //... and so on
Run Code Online (Sandbox Code Playgroud)

尝试#2

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

  if (loadSquare)
     square = 9'h1;

  if (loadDelta)
     delta = 9'h3;

  //... and so on
Run Code Online (Sandbox Code Playgroud)

当我运行模拟时,代码按预期工作,但我想更多地了解导致这些警告的原因。

Mor*_*gan 1

锁存器是一个基本的存储元件,它是打开或关闭的,即它是电平敏感的。触发器基本上是两个锁存器,其中一个锁存器对使能信号的反相进行操作,这使其对边沿敏感。

使用时,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
Run Code Online (Sandbox Code Playgroud)