我在Verilog中实现了一个简单的序列化程序,但我不了解何时阻止分配会导致问题的细微差别。我特别难以理解此答案的一部分。“但是,永远不要将阻塞分配用于同步通信,因为这是不确定的。”
我正在构建一个将其作为输入的块:
作为输出,我有:
每当有效数据变高时,该块便开始从位时钟的下一个上升沿开始,一次输出5位值。当最后一位丢失时,该块发出“完成”信号,因此可以使用新的5位值。
省略一些复位逻辑,执行此操作的代码如下所示:
always @ (posedge clk) begin
if(shiftIndex == 0) begin
if(dataValid == 1) transmitting = 1; //Blocking assign
else transmitting = 0; //Blocking assign
end
//Need the blocking assign up above to get this part to run
//for the 1st bit
if(transmitting == 1) begin
shiftIndex <= shiftIndex + 1;
dataOut <= data5b[shiftIndex];
if(shiftIndex == 4) begin
complete <= 1;
shiftIndex <= 0;
end
else begin
complete <= 0;
end
end
end
Run Code Online (Sandbox Code Playgroud)
现在,我可以使用所有非阻塞分配来编写该块,但是我觉得这会损害可读性。看起来像这样:
always @ (posedge clk) begin
if(shiftIndex == 0) begin
if(dataValid == 1) begin
transmitting <= 1; //Non-blocking now
shiftIndex <= shiftIndex + 1; //Duplicated code
dataOut <= data5b[shiftIndex]; //Duplicated code
complete <= 0; //Duplicated code
end
else transmitting <= 0;
end
//Now, this only runs for the 2nd, 3rd, 4th, and 5th bit.
else if(transmitting == 1) begin
shiftIndex <= shiftIndex + 1;
dataOut <= data5b[shiftIndex];
if(shiftIndex == 4) begin
complete <= 1;
shiftIndex <= 0;
end
else begin
complete <= 0;
end
end
end
Run Code Online (Sandbox Code Playgroud)
两者似乎都可以实现我在仿真中想要的功能,并且我喜欢第一个,因为它对我来说更容易阅读,但是由于我不明白为什么使用阻塞分配进行同步通信是不确定的,所以我担心自己已经编写了代码滴答定时炸弹
问题:当我尝试对此进行综合时,我在第一代码中做错了什么吗?尽管很难读(尽管对我而言),第二代码还是可取的吗?我应该做一些第三件事吗?
当使用阻塞 ( =
) 赋值时,该值可在下一行代码中使用。这意味着它是组合的并且不是由触发器驱动的。
在模拟中,它看起来像是由触发器驱动的,因为该模块仅在正时钟沿上进行评估,但实际上并非如此,这可能会破坏接口。
我属于永远不要混合样式的派别,因为这可能会成为代码审查和重构中的问题。重构,如果一个模块需要输出一个新信号并且发现它已经存在,那么它们只需更改为输出即可。乍一看,它像是一个触发器,因为它位于一个always @(posedge clk
块中。
因此,我建议不要混合样式,而是拉出组合部分并将其放在自己的块中。这还满足您的要求吗?如果没有的话你就会遇到问题。
我不知道如何控制数据有效,但它可以改变输出传输,潜在的传输也可能出现故障,因为它是来自组合解码,而不是从触发器干净地驱动。接收接口可能是异步的,故障可能会导致锁定等。
always @* begin
if(shiftIndex == 0) begin
if(dataValid == 1) transmitting = 1; //Blocking assign
else transmitting = 0; //Blocking assign
end
end
always @ (posedge clk) begin
if(transmitting == 1) begin
shiftIndex <= shiftIndex + 1;
dataOut <= data5b[shiftIndex];
if(shiftIndex == 4) begin
complete <= 1;
shiftIndex <= 0;
end
else begin
complete <= 0;
end
end
end
Run Code Online (Sandbox Code Playgroud)