?? account1.v
字號:
/*--------卡式電話計費器----------
本實驗假定通話時間disptime最長為59分鐘,卡內余額dispmoney最大數額為5元*/
//信號定義
//clk: 時鐘信號,頻率為1Hz
//card: 卡是否插入,高電平有效
//state: 電話接通信號,高電平有效
//decide: 電話局反饋回來的信號,代表話務種類,“01”表示市話,“10”表示長話,“11”表示特話。
//disptime: 顯示本次通話的時長,其單位為分鐘,這里假設能顯示的最大時間為59分鐘。
//dispmoney: 顯示卡內余額,其單位為角,這里假設能顯示的最大數額為5元,即50角。
//write,read: 當write信號下降沿到來時寫卡;當話卡插入,read信號變高讀卡。
//warn: 余額過少時的告警信號。當打市話時,余額少于3角,打長話時,余額少于6角,即會產生告警信號。
//cut: 當告警時間過長(>15s)時自動切斷通話信號。
//+num1和temp的輸出信號
module account1(clk,card,state,decide,disptime,dispmoney,write,read,warn,cut,t1m,
num10,temp1,money,set,reset_ena);
input clk,card,state;
input[1:0] decide;
output[7:0] disptime;
output[7:0] dispmoney;
output write,read,warn,cut,t1m;
output[31:0] num10,temp1;
output[7:0] money;
output set,reset_ena;
reg write,warn,cut;
reg[7:0] money; // 中間變量,用于計費(卡內余額),以t1m為時鐘信號!
reg[7:0] dtime; // 中間變量,用于通話計時,以t1m為時鐘信號!
reg t1m; // 中間變量——分時鐘,寫卡的時間
reg set,reset_ena; // set為“0”時置money初值;reset_ena為“0”時復位cut信號
integer num1,temp; // num1——對通話時間計數;temp——用于計告警時間
assign num10=num1;
assign temp1=temp;
assign dispmoney = card? money:0;//只要電話卡一插入,則顯示卡內余額;否則不顯示卡內余額
assign disptime = dtime;
assign read = card? 1:0; //只要電話卡一插入,則產生讀卡信號(高電平);否則讀卡信號為"0"。
// ----- 1.產生分時鐘
always @(posedge clk)
begin
if(num1==59) begin num1<=0; t1m<=1; end // 若計到59s,則num1清零,t1m=1
else
begin
if(state) num1<=num1+1; // 若接通線路,則num1開始加1計數
else num1<=0;
t1m<=0;
end
end
//----- 2.下面的always模塊完成電話計費和通話計時功能
always @(negedge clk)
begin
if(!set) // 置卡中金額初值為50角
begin set<=1;money<=12'd50;end
if(card && state) // 若卡已插入且線路已接通
if(t1m) // 若通話時間夠1分鐘(以t1m為計數器的時鐘信號)
case (decide)
2'b01:begin //(1)若話務為市話
if(money<3) //① 若卡上余額<3角,則告警
begin warn<=1;write<=0;reset_ena<=1;end
else
begin //② 若卡上余額>3角,則對市話計費
if(money[3:0]<4'b0011) // 若余額個位<3角
begin
money[3:0]<=money[3:0]+7; // 減3相當于加7(借位)
money[7:4]<=money[7:4]-1; // 十位減1
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]==5) // 最大可計時59分鐘
dtime[7:4]<=0;
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
end
2'b10:begin //(2)若話務為長話
if(money<6) //① 若卡上余額<6角,則告警
begin warn<=1;write<=0;reset_ena<=1;end
else
begin //② 若卡上余額>6角,則對長話計費
if(money[3:0]<6) // 若余額個位<6角
begin
money[3:0]<=money[3:0]+4;// 減6相當于加4(借位)
money[7:4]<=money[7:4]-1;
end
else money[3:0]<=money[3:0]-6;
//③ 對長話通話計時
if(dtime[3:0]==9)
begin
dtime[3:0]<=0;
if(dtime[7:4]==5)
begin dtime[7:4]<=0;end
else dtime[7:4]<=dtime[7:4]+1;
end
else dtime[3:0]<=dtime[3:0]+1;
write<=1;reset_ena<=0;warn<=0; //④寫卡
end
end
endcase
else write<=0; // 若t1m=0,則不寫卡
else // 若卡拔出或線路未接通,則對一些信號進行復位
begin dtime<=0;warn<=0;write<=0;reset_ena<=0;end
end
//----- 3.下面的always模塊在告警時間過長時切斷通話
always @(posedge clk)
begin
if(warn) temp<=temp+1; // 若有告警信號,則temp開始加1計數
else temp<=0; // 否則temp清零
if(temp==15) // 若計到15s
begin cut<=1;temp<=0;end // 則切斷通話
if(!card||!reset_ena) // 若卡已拔出,則復位cut信號
begin cut<=0;temp<=0;end
end
endmodule
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -