System verilog 在仲裁器的always_ff块中混合非阻塞和阻塞分配
我无法理解斯图尔特·萨瑟兰(及其同事)的书中的例子10-3 见第232行: 下面是代码片段。我的问题随后会提出System verilog 在仲裁器的always_ff块中混合非阻塞和阻塞分配,system-verilog,fsm,synthesis,round-robin,System Verilog,Fsm,Synthesis,Round Robin,我无法理解斯图尔特·萨瑟兰(及其同事)的书中的例子10-3 见第232行: 下面是代码片段。我的问题随后会提出 bit [0:NumRx-1] RoundRobin; always_ff @(posedge clk, posedge reset) begin: FSM bit breakVar; if (reset) begin: reset_logic Rxready <= '1; Txvalid <= '0; Txs
bit [0:NumRx-1] RoundRobin;
always_ff @(posedge clk, posedge reset) begin: FSM
bit breakVar;
if (reset) begin: reset_logic
Rxready <= '1;
Txvalid <= '0;
Txsel_out <= '0;
SquatState <= wait_rx_valid;
forward <= 0;
RoundRobin = 1;
end: reset_logic
else begin: FSM_sequencer
unique case (SquatState)
wait_rx_valid: begin: rx_valid_state
Rxready <= '1;
breakVar = 1;
for (int j=0; j<NumRx; j+=1) begin: loop1
for (int i=0; i<NumRx; i+=1) begin: loop2
if (Rxvalid[i] && RoundRobin[i] && breakVar)
begin: match
ATMcell <= RxATMcell[i];
Rxready[i] <= 0;
SquatState <= wait_rx_not_valid;
breakVar = 0;
end: match
end: loop2
if (breakVar)
RoundRobin={RoundRobin[1:$bits(RoundRobin)-1],
RoundRobin[0]};
end: loop1
end: rx_valid_state
位[0:NumRx-1]循环;
始终_ff@(posedge时钟、posedge重置)开始:FSM
位突变;
如果(复位)开始:复位逻辑
Rxready决不能将阻塞和非阻塞赋值混合到同一个变量breakVar
是一个临时变量,它将被合成为组合逻辑,因为它总是先写入,然后读取。没有要保存的状态RoundRobin
是一个局部变量,用作中间变量和状态变量。但是,由于它只能从始终\u ff
块中访问,因此不存在竞争条件的危险
临时变量只是表示一个等式的符号方式。下面是一个不同但更简单的示例:
always_ff @(posedge clock)
begin
full = (counter == 10);
brimming = (counter > 7);
hold <= brimming && !full;
if (full)
counter <= counter + 1;
else
counter < = 0;
end
始终\u ff@(posedge时钟)
开始
满=(计数器==10);
满溢=(计数器>7);
hold完全同意答案
您应该始终在always\u comb块中拆分逻辑元素,并在always\u ff块中拆分顺序元素
- 如果您编写的代码是如此紧密地缝合在一起(两个
和同一块中的顺序元素),即使它正确且
符合系统verilog规范,一些较旧版本的模拟器
或者,正在开发的新模拟器可能会以错误的方式推断它
- 您的代码将不干净,其他人无法理解
- 同样,以上述风格写作,你只是在压缩文章的行数
代码,即使逻辑保持不变。这是毫无意义的
如果编写紧凑的代码会妨碍代码的可读性,则编写紧凑的代码
现在,就阻塞语句和非阻塞语句的使用而言,我认为辩论现在结束了。现在,在always\u comb块中使用阻塞语句和在always\u ff块中使用非阻塞语句更多地是一种规则而不是指导原则
然而,Clifford E Cummings在这篇精彩的论文中解释了你所有问题的答案
如果您对verilog/system verilog设计不熟悉,我建议您阅读他们的所有论文,它们非常有用,为RTL设计工程师奠定了良好的基础
另外,这里可能讲得太多了,但如果您正在寻找如何在组合块和顺序块中分离代码,您可以查看由
信号名称很难一下子理解,但如果仔细观察,代码在逻辑上非常简洁,不会因模拟和合成工具的突发奇想而留下任何东西。我不确定这是否正确-RoundRobin
在本例中是一个寄存器,应该真的使用非阻塞分配。我有一半是正确的-RoundRobin
存储状态,但在写入循环后也会读取,因此需要阻塞分配。。。我的评论有点误导,但你发现了故意的错误;)2 always块方法更干净,尽管它需要更多的输入。一个always\u comb
用于所有阻塞分配,包括下一个\u状态值,一个always\u ff
用于非阻塞分配状态到下一个\u状态。这样可以在波形中看到D引脚,这对调试非常有用。我发现它使ECOs更容易操作和记录。根据,2-always方法提供了更好的面积和时间,但我认为它确实依赖于工具/版本。@dave_59,你能详细说明一下临时变量是如何合成的吗?更新的答案。你引用的论文是关于Verilog而不是SystemVerilog的。@ShashankVM SystemVerilog是Verilog的超集,同样的概念也适用。
always_ff @(posedge clock)
begin
hold <= (counter > 7) && !(counter == 10);
if (counter == 10)
counter <= counter + 1;
else
counter < = 0;
end