在尝试编译和模拟Verilog模块和激励时,我收到了一些奇怪的结果。如果我在Silos中模拟它,代码将按预期运行。如果我在Icarus(iverlog和vvp)中模拟它的时间与Silos不同(从0开始而不是200,我不关心Silos有235 - > 255并且Icarus有235 - > 265)。 Silos重复功能正如我所料,但是当使用Icarus时,我似乎无法弄清楚他们是如何得到这个结果的。此外,当将重复R2GDELAY更改为3时,Icarus似乎也没有像预期的那样预先形成。在使用Icarus时是否有我遗漏的东西,例如我必须手动将开始时间设置为0以便在模拟后期得到准确的结果,或者Silos自动初始化我必须在Icarus中手动完成的变量?此代码来自Verilog HDL书籍,可在此处找到http://authors.phptr.com/palnitkar/
以下是代码:
`define TRUE 1'b1
`define FALSE 1'b0
`define RED 2'd0
`define YELLOW 2'd1
`define GREEN 2'd2
//State definition HWY CNTRY
`define S0 3'd0 //GREEN RED
`define S1 3'd1 //YELLOW RED
`define S2 3'd2 //RED RED
`define S3 3'd3 //RED GREEN
`define S4 3'd4 //RED YELLOW
//Delays
`define Y2RDELAY 3 //Yellow to red delay
`define R2GDELAY 2 //Red to Green Delay
module sig_control (hwy, cntry, X, clock, clear);
//I/O ports
output [1:0] hwy, cntry;
//2 bit output for 3 states of signal
//GREEN, YELLOW, RED;
reg [1:0] hwy, cntry;
//declare output signals are registers
input X;
//if TRUE, indicates that there is car on
//the country road, otherwise FALSE
input clock, clear;
//Internal state variables
reg [2:0] state;
reg [2:0] next_state;
initial
begin
state = `S0;
next_state = `S0;
hwy = `GREEN;
cntry = `RED;
end
//state changes only at positive edge of clock
always @(posedge clock)
state = next_state;
//Compute values of main signal and country signal
always @(state)
begin
case(state)
`S0: begin
hwy = `GREEN;
cntry = `RED;
end
`S1: begin
hwy = `YELLOW;
cntry = `RED;
end
`S2: begin
hwy = `RED;
cntry = `RED;
end
`S3: begin
hwy = `RED;
cntry = `GREEN;
end
`S4: begin
hwy = `RED;
cntry = `YELLOW;
end
endcase
end
//State machine using case statements
always @(state or X)
begin
if(clear)
next_state = `S0;
else
case (state)
`S0: if(X)
next_state = `S1;
else
next_state = `S0;
`S1: begin //delay some positive edges of clock
repeat(`Y2RDELAY) @(posedge clock) ;
next_state = `S2;
end
`S2: begin //delay some positive edges of clock
//EDIT ADDED SEMICOLON
repeat(`R2GDELAY) @(posedge clock);
next_state = `S3;
end
`S3: if( X)
next_state = `S3;
else
next_state = `S4;
`S4: begin //delay some positive edges of clock
repeat(`Y2RDELAY) @(posedge clock) ;
next_state = `S0;
end
default: next_state = `S0;
endcase
end
endmodule
//Stimulus Module
module stimulus;
wire [1:0] MAIN_SIG, CNTRY_SIG;
reg CAR_ON_CNTRY_RD;
//if TRUE, indicates that there is car on
//the country road
reg CLOCK, CLEAR;
//Instantiate signal controller
sig_control SC(MAIN_SIG, CNTRY_SIG, CAR_ON_CNTRY_RD, CLOCK, CLEAR);
//Setup monitor
initial
$monitor($time, " Main Sig = %b Country Sig = %b Car_on_cntry = %b",
MAIN_SIG, CNTRY_SIG, CAR_ON_CNTRY_RD);
//setup clock
initial
begin
CLOCK = `FALSE;
forever #5 CLOCK = ~CLOCK;
end
//control clear signal
initial
begin
CLEAR = `TRUE;
repeat (5) @(negedge CLOCK);
CLEAR = `FALSE;
end
//apply stimulus
initial
begin
CAR_ON_CNTRY_RD = `FALSE;
#200 CAR_ON_CNTRY_RD = `TRUE;
#100 CAR_ON_CNTRY_RD = `FALSE;
#200 CAR_ON_CNTRY_RD = `TRUE;
#100 CAR_ON_CNTRY_RD = `FALSE;
#200 CAR_ON_CNTRY_RD = `TRUE;
#100 CAR_ON_CNTRY_RD = `FALSE;
#100 $finish;
end
endmodule
以下是Silos的输出:
200 Main Sig = 10 Country Sig = 00 Car_on_cntry = 1
205 Main Sig = 01 Country Sig = 00 Car_on_cntry = 1
235 Main Sig = 00 Country Sig = 00 Car_on_cntry = 1
255 Main Sig = 00 Country Sig = 10 Car_on_cntry = 1
300 Main Sig = 00 Country Sig = 10 Car_on_cntry = 0
305 Main Sig = 00 Country Sig = 01 Car_on_cntry = 0
335 Main Sig = 10 Country Sig = 00 Car_on_cntry = 0
500 Main Sig = 10 Country Sig = 00 Car_on_cntry = 1
505 Main Sig = 01 Country Sig = 00 Car_on_cntry = 1
535 Main Sig = 00 Country Sig = 00 Car_on_cntry = 1
555 Main Sig = 00 Country Sig = 10 Car_on_cntry = 1
600 Main Sig = 00 Country Sig = 10 Car_on_cntry = 0
605 Main Sig = 00 Country Sig = 01 Car_on_cntry = 0
635 Main Sig = 10 Country Sig = 00 Car_on_cntry = 0
800 Main Sig = 10 Country Sig = 00 Car_on_cntry = 1
805 Main Sig = 01 Country Sig = 00 Car_on_cntry = 1
835 Main Sig = 00 Country Sig = 00 Car_on_cntry = 1
855 Main Sig = 00 Country Sig = 10 Car_on_cntry = 1
900 Main Sig = 00 Country Sig = 10 Car_on_cntry = 0
905 Main Sig = 00 Country Sig = 01 Car_on_cntry = 0
935 Main Sig = 10 Country Sig = 00 Car_on_cntry = 0
以下是iverilog的输出:
0 Main Sig = 10 Country Sig = 00 Car_on_cntry = 0
200 Main Sig = 10 Country Sig = 00 Car_on_cntry = 1
205 Main Sig = 01 Country Sig = 00 Car_on_cntry = 1
235 Main Sig = 00 Country Sig = 00 Car_on_cntry = 1
265 Main Sig = 00 Country Sig = 10 Car_on_cntry = 1
300 Main Sig = 00 Country Sig = 10 Car_on_cntry = 0
305 Main Sig = 00 Country Sig = 01 Car_on_cntry = 0
335 Main Sig = 10 Country Sig = 00 Car_on_cntry = 0
500 Main Sig = 10 Country Sig = 00 Car_on_cntry = 1
505 Main Sig = 01 Country Sig = 00 Car_on_cntry = 1
535 Main Sig = 00 Country Sig = 00 Car_on_cntry = 1
565 Main Sig = 00 Country Sig = 10 Car_on_cntry = 1
600 Main Sig = 00 Country Sig = 10 Car_on_cntry = 0
605 Main Sig = 00 Country Sig = 01 Car_on_cntry = 0
635 Main Sig = 10 Country Sig = 00 Car_on_cntry = 0
800 Main Sig = 10 Country Sig = 00 Car_on_cntry = 1
805 Main Sig = 01 Country Sig = 00 Car_on_cntry = 1
835 Main Sig = 00 Country Sig = 00 Car_on_cntry = 1
865 Main Sig = 00 Country Sig = 10 Car_on_cntry = 1
900 Main Sig = 00 Country Sig = 10 Car_on_cntry = 0
905 Main Sig = 00 Country Sig = 01 Car_on_cntry = 0
935 Main Sig = 10 Country Sig = 00 Car_on_cntry = 0
编辑:添加分号,如上面的代码所示 谢谢你的帮助!
答案 0 :(得分:3)
您的逻辑中存在竞争条件,如评论中所述,您不应将时钟用作组合逻辑的输入。
查看以下两个逻辑块:
1. repeat(`R2GDELAY) @(posedge clock)
next_state = `S3;
2. always @(posedge clock)
state = next_state;
当出现posedge时钟时,模拟器将首先执行这两个语句中的一个,而没有关于它可能选择的规则。如果它首先选择#1,则下一个状态将被设置为S3,然后#2将执行,将状态分配给S3。如果#2先执行,则state将设置为其他值,然后在分配状态后将next_state设置为S3。
现在,根据模拟器首先选择执行的随机事件,您会有不同的行为。
避免这种情况的方法不是让你的组合模块以任何方式看时钟。时钟应仅用于更新寄存器,使用非阻塞分配<=
。