- 主题:verilog组合逻辑控制同一个变量读写的问题
代码如下:
module my_module(
input wire clk,
input wire rst,
input wire ina,
input wire inb,
...
);
reg[1:0] queue;
reg[3:0] cur_state, next_state;
reg[1:0] value;
always @(posedge clk) begin
if (rst) begin
next_state <= 4'b0000;
end else begin
next_state <= cur_state;
end
end
always @(*) begin
if (rst) begin
queue = 2'b00;
end else begin
if (ina) begin
queue[0] = 1'b1;
end
if (inb) begin
queue[1] = 2'b1;
end
case (cur_state)
4'b0000: begin
if (queue[0]) begin
value = 2'b01;
next_state = 4'b0001;
end else if (queue[1]) begin
value = 2'b10;
next_state = 4'b0001;
end
end
4'b0001: begin
if (value...)
...
end
end
end
endmodule
这段代码的逻辑类似于总线接口,它分别接受来自inst/data cache的访问请求(可能同时),inst访问优先于data,所以在0000状态里用if/else,之后就是同步的逻辑,直到下一次进入0000状态并且queue有访问继续。
用modelsim仿真完全没有问题,但是用verilator去仿真会得到"active region value did not converge"的错误,就是说value的值在快速变化。我后来理解了,是因为在0000状态,queue的值是随时会变化的,因为是组合电路导致value的值也在随时变化(虽然ina/inb都只一个持续一个时钟周期)。
把FSM第二段改成时序逻辑应该是能解决这个问题,因为这样queue值只在时钟上升沿发生变化,但执行时间会化更多时钟周期。
哪位大神好招吗?
--
FROM 125.33.202.*
你自己都说的ina和inb是if/else的关系,
然而你的代码并没有写成if/else的关系:
if (ina) begin
queue[0] = 1'b1;
end
if (inb) begin
queue[1] = 2'b1;
end
【 在 liriver 的大作中提到: 】
: 代码如下:
: module my_module(
: input wire clk,
: ...................
--
FROM 70.190.162.130
你没看仔细,我说的if/else是只0000状态里的呀,ina/inb是可能同时的,我说明了的。就好比
inst/data request是可能同时的,但你后面处理肯定是一个一个的,所以这也是为什么queue里0位的优先(代码优先)
if (queue[0])
...
else if (queue[1])
...
【 在 chenpp 的大作中提到: 】
: 你自己都说的ina和inb是if/else的关系,
: 然而你的代码并没有写成if/else的关系:
: if (ina) begin
: ...................
--
FROM 125.33.202.*
这个queue是为了记住request序列,因为request只持续一拍,下一拍这个信号就消失了,不记住这信号不就丢失了吗
【 在 chenpp 的大作中提到: 】
: 你自己都说的ina和inb是if/else的关系,
: 然而你的代码并没有写成if/else的关系:
: if (ina) begin
: ...................
--
FROM 125.33.202.*
解决了,傻了,最简单就是把
if (ina) begin
queue[0] = 1'b1;
end
if (inb) begin
queue[1] = 2'b1;
end
这段移入时序逻辑就行,这样queue只有在时钟上升沿改变一次而不会像组合电路一样是一种随时改变的状态电路
--
FROM 125.33.202.*