/*信号定义:
clk:时钟信号,本例中其频率值为1Hz;
decide:电话局反馈回来的信号,代表话务种类,“01”表示市话,“10”表示 长话,“11”表示特话;
dispmoney: 用来显示卡内余额,其单位为角,这里假定能显示的最大数额为50元(500角);
disptime:显示本次通话的时长;
write,read: 当write信号下降沿到来时写卡,当话卡插入,read信号变高时读卡;
warn:余额过少时的告警信号。本例中,当打市话时,余额少于3角,打长
话时,余额少于6角,即会产生告警信号;
cut:当告警时间过长时自动切断通话信号。*/
module account(state,clk,card,decide,disptime,dispmoney,
write,read,warn,cut);
output write,read,warn,cut;
input state,clk,card;
input[2:1] decide;
output[10:0] dispmoney;
output[8:0] disptime;
reg[10:0] money;
reg[8:0] dtime;
reg warn,cut,write,t1m;//t1m为分时钟
reg set,reset_ena;
integer num1,temp;
assigndispmoney=card?money:0;
assigndisptime=dtime;
assignread=card?1:0;
always @(posedge clk)
begin
if (num1==59)beginnum1<=0;t1m<=1;end
elsebegin
if(state)num1<=num1+1;
elsenum1<=0;t1m<=0;
end
end
always @(negedge clk)//该进程完成电话计费功能
begin
if(!set)
beginmoney<=11'h500;set<=1;end
if(card&state)
if(t1m)
case({state,decide})
3'b101:if(money<3)
beginwarn<=1;write<=0;reset_ena<=1;end
else
begin//市话计费
if(money[3:0]<4'b0011)
begin
money[3:0]<=money[3:0]+7;
if(money[7:4]!=0)
money[7:4]<=money[7:4]-1;
else
beginmoney[7:4]<=9;money[10:8]<=money[10:8]-1;end
end
elsemoney[3:0]<=money[3:0]-3;write<=1;
//市话通话计时
if(dtime[3:0]==9)
begin
dtime[3:0]<=0;
if(dtime[7:4]==9)
begindtime[7:4]<=0;dtime[8]<=dtime[8]+1;end
elsedtime[7:4]<=dtime[7:4]+1;
end
else
begin
dtime[3:0]<=dtime[3:0]+1;warn<=0;reset_ena<=0;
end
end
3'b110:if(money<6)
beginwarn<=1;write<=0;reset_ena<=1;end
else begin
//通话计时
if(dtime[3:0]==9)
begin
dtime[3:0]<=0;if(dtime[7:4]==9)
begindtime[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;
//长话计费
if(money[3:0]<4'b0110)
begin
money[3:0]<=money[3:0]+4;
if(!money[7:4])
beginmoney[7:4]<=9;money[10:8]<=money[10:8]-1;end
elsemoney[7:4]<=money[7:4]-1;
end
elsemoney[3:0]<=money[3:0]-6;
write<=1;reset_ena<=0;warn<=0;
end
endcase
else write<=0;
elsebegindtime<=0;warn<=0;write<=0;reset_ena<=0;en
//取卡后对一些信号进行复位
end
always @(posedge clk)//该进程在告警时间过长的情况下切断本次通话
begin
if(warn)temp<=temp+1;
else temp<=0;
if(temp==15)
begincut<=1;temp<=0;end
if(!card||!reset_ena)
begin
cut<=0;//复位cut信号
temp<=0;
end
end
endmodule