verilog的高手帮忙看一下这个程序,仿真的时候只有read有结果,其他全部是0??
/*信号定义:
clk: 时钟信号,本例中其频率值为 1Hz;
decide: 电话局反馈回来的信号,代表话务种类,“01”表示市话,“10”表示
长话,“11”表示特话;
dispmoney: 用来显示卡内余额,其单位为角,这里假定能显示的最大数额为 50 元
(500 角);
disptime: 显示本次通话的时长;
write,read: 当 write 信号下降沿到来时写卡,当话卡插入,read 信号变高时读卡;
warn: 余额过少时的告警信号。本例中,当打市话时,余额少于 3 角,打长
话时,余额少于 6 角,即会产生告警信号;
cut: 当告警时间过长时自动切断通话信号。 */
module acc1(state,clk,card,decide,disptime,dispmoney,
write,read,warn,cut);
input state,clk,card;//state为1时表示正在通话中 card为1时表示已插入卡
input[2:1] decide;
output write,read,warn,cut;
reg write,warn,cut;
output[10:0] dispmoney;
output[8:0] disptime;
reg [10:0] money;
reg [8:0] dtime;
reg minute; //分
reg set,reset_ena;
integer temp,second;
assign dispmoney=card?money:0;
assign disptime=dtime;
assign read=card?1:0;
initial
begin
dtime=0;
money=0;
minute=0;
temp=0;second=0;reset_ena=0;set=0;
end
//产生分钟
always @(posedge clk)
begin
if(card&state)
begin
second<=second+1;
if (second==60) begin second<=0; minute<=1; end
if (second==1) minute<=0;
end
else begin second<=0; minute<=0; end
end
always @(negedge clk) //该进程完成电话计费计时功能 写滞后
begin
write=1;
if(!set)
begin money=11'h500; set=1;end
if(card&state)
if(minute)
begin
case(decide)
2'b01: if(money<3)
begin warn=1; write=0; reset_ena=1; end
else
begin
//市话计费 一分钟3角
if(money[3:0]<3)
begin
if(money[7:4]!=0)
begin money[7:4]=money[7:4]-1;money[3:0]=money[3:0]+7; end
else
begin money[10:8]=money[10:8]-1; money[7:4]=9; money[3:0]=money[3:0]+7;end
end
else begin money[3:0]=money[3:0]-3; write=1; end
//市话通话计时 以分钟计 最多打166分钟
if(dtime[3:0]==9)
begin
dtime[3:0]=0;
if(dtime[7:4]==9)
begin dtime[7:4]=0; dtime[8]=dtime[8]+1; end
else dtime[7:4]=dtime[7:4]+1;
end
else
dtime[3:0]=dtime[3:0]+1;
end
2'b10: if(money<6)
begin warn=1; write=0; reset_ena=1; end
else
begin
//长话计费
if(money[3:0]<6)
begin
if(money[7:4]!=0)
begin money[7:4]=money[7:4]-1;money[3:0]=money[3:0]+4; end
else
begin money[10:8]=money[10:8]-1; money[7:4]=9; money[3:0]=money[3:0]+4;end
end
else begin money[3:0]=money[3:0]-6; write=1; end
//通话计时
if(dtime[3:0]==9)
begin
dtime[3:0]=0;
if(dtime[7:4]==9)
begin dtime[7:4]=0; dtime[8]=dtime[8]+1; end
else dtime[7:4]=dtime[7:4]+1;
end
else dtime[3:0]=dtime[3:0]+1;
end
endcase
end //end if(!minute)
else write=0; //不到一分钟不写卡
else begin dtime=0; warn=0; write=0; reset_ena=0; end
//取卡或不在通话状态对一些信号进行复位
end
always @(posedge clk) //该进程在告警时间过长的情况下切断本次通话
begin
if(warn) temp=temp+1;
else temp=0;
if(temp==15)
begin cut=1; temp=0; end
if(!card||!reset_ena)
begin
cut=0; //复位cut 信号
temp=0;
end
end
endmodule
[解决办法]
算不上是高手,说几点建议:
1、代码有点乱,层次不是很清楚,if...else,begin...end,等应对齐放置
2、寄存器赋值应该使用非阻塞赋值‘<=’,使用‘=’赋值有时会出现意料不到的结果
3、数组赋值时给一个固定的宽度,减少编译告警
4、说这么多,仅供你参考
把你的代码改了一下,看看对你有没有帮助,呵呵
/*
信号定义:
clk: 时钟信号,本例中其频率值为 1Hz;
decide: 电话局反馈回来的信号,代表话务种类,“01”表示市话,“10”表示
长话,“11”表示特话;
dispmoney: 用来显示卡内余额,其单位为角,这里假定能显示的最大数额为 50 元
(500 角);
disptime: 显示本次通话的时长;
write,read: 当 write 信号下降沿到来时写卡,当话卡插入,read 信号变高时读卡;
warn: 余额过少时的告警信号。本例中,当打市话时,余额少于 3 角,打长
话时,余额少于 6 角,即会产生告警信号;
cut: 当告警时间过长时自动切断通话信号。
*/
module acc1(state,clk,card,decide,disptime,dispmoney,write,read,warn,cut);
input state,clk,card;//state为1时表示正在通话中 card为1时表示已插入卡
input[2:1] decide;
output write,read,warn,cut;
reg write,warn,cut;
output[10:0] dispmoney;
output[8:0] disptime;
reg [10:0] money;
reg [8:0] dtime;
reg minute; //分
reg set,reset_ena;
integer temp,second;
assign dispmoney =card ? money : 0;
assign disptime = dtime;
assign read = card ? 1 : 0;
initial
begin
dtime=0;
money=0;
minute=0;
temp=0;second=0;reset_ena=0;set=0;
end
//产生分钟
always @(posedge clk)
begin
if(card & state)
begin
second <= second + 1;
if (second==60)
begin
second <= 0;
minute <= 1;
end
if (second==1)
begin
minute <= 0;
end
end
else
begin
second <=0;
minute <=0;
end
end
always @(negedge clk) //该进程完成电话计费计时功能 写滞后
begin
write=1;
if(!set)
begin
money <= 11'h500;
set <= 1'b1;
end
if(card&state)
if(minute)
begin
case(decide)
2'b01: if(money <3)
begin
warn <= 1;
write <= 0;
reset_ena <= 1;
end
else
begin //市话计费 一分钟3角
if(money[3:0] <3)
begin
if(money[7:4]!=0)
begin
money[7:4] <= money[7:4] - 1;
money[3:0] <= money[3:0] + 7;
end
else
begin
money[10:8] <=money[10:8] - 1;
money[7:4] <= 9;
money[3:0] <= money[3:0] + 7;
end
end
else
begin
money[3:0] <= money[3:0] - 3;
write <= 1;
end
//市话通话计时 以分钟计 最多打166分钟
if(dtime[3:0]==9)
begin
dtime[3:0] <= 0;
if(dtime[7:4]==9)
begin
dtime[7:4] <= 0;
dtime[8] <= dtime[8] + 1;
end
else
begin
dtime[7:4] <= dtime[7:4] + 1;
end
end
else
dtime[3:0] <= dtime[3:0] + 1;
end
2'b10: if(money <6)
begin
warn <= 1;
write <= 0;
reset_ena <= 1;
end
else
begin //长话计费
if(money[3:0] <6)
begin
if(money[7:4]!=0)
begin
money[7:4] <= money[7:4] - 1;
money[3:0] <= money[3:0] + 4;
end
else
begin
money[10:8] <= money[10:8] - 1;
money[7:4] <= 9;
money[3:0] <= money[3:0] + 4;
end
end
else
begin
money[3:0] <= money[3:0] - 6;
write <= 1;
end
//通话计时
if(dtime[3:0]==9)
begin
dtime[3:0] <= 0;
if(dtime[7:4]==9)
begin
dtime[7:4] <= 0;
dtime[8] <= dtime[8] + 1;
end
else
begin
dtime[7:4] <= dtime[7:4] + 1;
end
end
else
begin
dtime[3:0] <= dtime[3:0] + 1;
end
end
endcase
end //end if(!minute)
else
write=0; //不到一分钟不写卡
else
begin
dtime <= 0;
warn <= 0;
write <= 0;
reset_ena <=0;
end
//取卡或不在通话状态对一些信号进行复位
end
always @(posedge clk) //该进程在告警时间过长的情况下切断本次通话
begin
if(warn)
temp <= temp + 1;
else
temp <= 0;
if(temp==15)
begin
cut <= 1;
temp <= 0;
end
if(!card||!reset_ena)
begin
cut <= 0; //复位cut 信号
temp <= 0;
end
end
endmodule