我正在Verilog中实现一个简单的序列化器,但我不理解阻塞赋值的细微差别。我特别难以理解这个答案的一部分。"然而,您永远不应该使用阻塞分配进行同步通信,因为这是不确定性的。"
我正在构建一个块,它以以下内容作为输入:
- 一个位时钟 - 一个5位并行数据输入(要序列化的值) - 一个“数据有效”信号,表示存在有效的5位数据
作为输出,我有:
- 串行数据输出 - 一个“完成”信号,表示已经到了新的5位值的时间 - 一个“传输”信号,当总线上有有效的串行数据时高电平
每当数据有效变为高电平时,该块就开始输出5位值,从下一个位时钟上升沿开始,每次输出一个位。当最后一个位在导线上时,该块发出“完成”信号,以便提供新的5位值。
省略一些重置逻辑,执行此操作的代码如下:
我正在构建一个块,它以以下内容作为输入:
- 一个位时钟 - 一个5位并行数据输入(要序列化的值) - 一个“数据有效”信号,表示存在有效的5位数据
作为输出,我有:
- 串行数据输出 - 一个“完成”信号,表示已经到了新的5位值的时间 - 一个“传输”信号,当总线上有有效的串行数据时高电平
每当数据有效变为高电平时,该块就开始输出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
现在,我可以用所有非阻塞分配来编写块,但我觉得这会影响可读性。它看起来可能像这样:
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
两者在模拟中都能实现我想要的效果,我更喜欢第一个,因为它对我来说更易于阅读。但由于我不明白为什么同步通信需要使用阻塞分配,这是不确定的,我担心我编写了一颗定时炸弹。
问题:在第一个代码中是否存在错误,当我尝试合成时会爆炸?第二个代码是否更可取,尽管有点难(对我而言)阅读?还有些第三件事我应该做吗?
=
设置变量,并在同一周期内使用新值,则该值不能使用触发器生成,因此是组合逻辑,而不是同步逻辑。 - Morgan