/*信號定義:
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;
assign dispmoney=card?money:0;
assign disptime=dtime;
assign read=card?1:0;
always @(posedge clk)
begin
if (num1==59) begin num1<=0; t1m<=1; end
else begin
if(state) num1<=num1+1;
else num1<=0; t1m<=0;
end
end
always @(negedge clk) //該進程完成電話計費功能
begin
if(!set)
begin money<=11'h500; set<=1; end
if(card&state)
if(t1m)
case({state,decide})
3'b101: if(money<3)
begin warn<=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
begin money[7:4]<=9; money[10:8]<=money[10:8]-1; end
end
else money[3:0]<=money[3:0]-3; write<=1;
//市話通話計時
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
begin
dtime[3:0]<=dtime[3:0]+1; warn<=0; reset_ena<=0;
end
end
3'b110: if(money<6)
begin warn<=1; write<=0; reset_ena<=1; end
else begin
//通話計時
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;
//長話計費
if(money[3:0]<4'b0110)
begin
money[3:0]<=money[3:0]+4;
if(!money[7:4])
begin money[7:4]<=9; money[10:8]<=money[10:8]-1; end
else money[7:4]<=money[7:4]-1;
end
else money[3:0]<=money[3:0]-6;
write<=1; reset_ena<=0; warn<=0;
end
endcase
else write<=0;
else begin dtime<=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)
begin cut<=1; temp<=0; end
if(!card||!reset_ena)
begin
cut<=0; //複位cut信號
temp<=0;
end
end
endmodule
[admin via 研發互助社區 ] Verilog電話計費器的代碼已經有2283次圍觀
http://cocdig.com/docs/show-post-42986.html