edc*_*edc 1 synthesis fsm round-robin system-verilog
我无法理解Stuart Sutherland(和他的同事)所著SystemVerilog For Design书中的示例 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;
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
Run Code Online (Sandbox Code Playgroud)
具体来说,我的问题是关于阻塞分配breakVar和RoundRobin。我在某处读到变量是本地评估的,但我无法想象逻辑是如何合成的。是否RoundRobin被合成到状态寄存器?
大多数指导方针声明永远不要混合阻塞和非阻塞分配。有没有更好的方法来表示这样的东西?鉴于它在一个always_ff块中,现在在 SystemVerilog 设计中可以混合两种类型的赋值吗?
永远不要将阻塞和非阻塞赋值混合到同一个变量。breakVar是一个临时变量,将被合成为组合逻辑,因为它总是先写入,然后再读取。没有要保存的状态。RoundRobin是一个局部变量,同时用作中间变量和状态变量。但是因为它只能从always_ff块内访问,所以不存在竞争条件的危险。
临时变量只是表示方程的一种象征方式。这是一个不同但更简单的例子:
always_ff @(posedge clock)
begin
full = (counter == 10);
brimming = (counter > 7);
hold <= brimming && !full;
if (full)
counter <= counter + 1;
else
counter < = 0;
end
Run Code Online (Sandbox Code Playgroud)
这相当于编写以下内容(但可能更难理解)
always_ff @(posedge clock)
begin
hold <= (counter > 7) && !(counter == 10);
if (counter == 10)
counter <= counter + 1;
else
counter < = 0;
end
Run Code Online (Sandbox Code Playgroud)
在上面的两个例子中,counter总是被综合为一个寄存器,因为它是先读后写。无论我们使用阻塞赋值还是非阻塞赋值都没有关系,因为我们counter在写入之后从不读取。always_ff使用阻塞赋值的块内没有竞争条件,但如果有另一个always_ff块试图读取它,则可能存在竞争条件。由于full和brimming是在读取之前写入的,因此不必注册。
总而言之,如果这些条件中的任何一个为真,则变量将被合成为寄存器
always_ff块中并在块外读取。