設(shè)計背景:
計算器是設(shè)計中經(jīng)常用到的一個操作軟件,設(shè)計和學(xué)習(xí)計算器使我們親密的聯(lián)系所學(xué)的各模塊, 對我們的學(xué)習(xí)有很大的幫助和提升。希望大家來學(xué)習(xí)
設(shè)計原理:
本次的設(shè)計主要通過矩陣鍵盤來實現(xiàn)按鍵的加減乘除運(yùn)算,通過按下有效鍵值來當(dāng)被加數(shù)或者被除數(shù)等等,按下10 -- 13等數(shù)字來表示對應(yīng)的運(yùn)算符。按鍵鍵值15表示等于號。
此次的設(shè)計是通過數(shù)碼管來實現(xiàn)顯示的,通過按下對應(yīng)的按鍵來顯示到數(shù)碼管上,百位十位個位等等。當(dāng)按下運(yùn)算算符的時候顯示清0不顯示東西,之后通過繼續(xù)按下別的鍵值來顯示出對應(yīng)的加數(shù)和除數(shù)等等,之后通過按下對應(yīng)的鍵值15表示等于后,然后數(shù)碼管清0之后立馬顯示出對應(yīng)的等于的數(shù)。
這樣來完成我們此次的設(shè)計。
設(shè)計架構(gòu)圖:
設(shè)計代碼:
頂層模塊
0modulecalc(clk,rst_n,row,col,sel,seg7); //端口列表
1 inputclk; //時鐘
2 inputrst_n; //復(fù)位
3 input[3:0]row; //行信號
4
5 output[3:0]col; //列信號
6 output[2:0]sel; //數(shù)碼管位選信號
7 output[7:0]seg7; //數(shù)碼管段選信號
8
9 wire[23:0]data;
10
11 //例化數(shù)碼管模,和矩陣鍵盤模塊
12 key_borad key_borad_dut(
13 .clk(clk),
14 .rst_n(rst_n),
15 .row(row),
16 .col(col),
17 .data(data)
18 );
19 seg seg_dut(
20 .clk(clk),
21 .rst_n(rst_n),
22 .sel(sel),
23 .seg7(seg7),
24 .data_in(data)
25 );
26
27endmodule
設(shè)計模塊
0modulekey_borad(clk,rst_n,row,col,data);
1 inputclk; //時鐘 50M
2 inputrst_n; //復(fù)位
3 input[3:0]row; //輸入行信號
4
5 outputreg[3:0]col; //輸出列信號
6 outputreg[23:0]data;
7
8 //狀態(tài)變量,表示
9 parameters0 =3'b00;
10 parameters1 =3'b01;
11 parameters2 =3'b10;
12 parameters3 =3'b11;
13 parameters4 =3'b100;
14 parameters5 =3'b101;
15
16 parameterT1ms =50000;//掃描間隔
17 //parameter T1ms = 2;
18 parameterT10ms=500_000;//按鍵消抖時間
19 //parameter T10ms = 20;
20
21 wireflag;
22 reg[15:0]count;
23 always@(posedgeclk ornegedgerst_n)
24 if(!rst_n)
25 begin
26 count <=16'd0;
27 end
28 else
29 begin
30 if(count ?T1ms -1) ? //計數(shù)1K的頻率時間
31 count <=?count +1'b1;
32 else
33 begin
34 count <=16'b0;
35 end
36 end
37
38 assignflag =(count ==T1ms -1)?1'b1:1'b0; //計數(shù)到了就給一個高脈沖,反之低脈沖
39
40 reg[2:0]state;
41 reg[7:0]row_col;
42 reg[18:0]cnt;
43 regdata_flag;
44 always@(posedgeclk ornegedgerst_n)
45 if(!rst_n)
46 begin
47 state <=3'b0;
48 row_col <=8'b1111_1111;
49 data_flag <=1'b0;
50 col <=4'b0000;
51 cnt <=19'b0;
52 end
53 else
54 begin
55 case(state)
56 s0:begin
57 if(row ==4'b1111) //如果沒有按下
58 begin
59 data_flag <=1'b0;
60 col <=4'b0000;
61 end
62 else //表示按下,跳轉(zhuǎn)下一個狀態(tài)
63 begin
64 data_flag <=1'b0;
65 state <=?s1;
66 end
67 end
68 s1:begin
69 if(row ==4'b1111) //如果是抖動跳轉(zhuǎn)0狀態(tài)
70 begin
71 cnt <=19'b0;
72 state <=?s0;
73 end
74 else
75 begin
76 if(cnt
77 begin
78 cnt <=?cnt +1'b1;
79 end
80 else
81 begin
82 cnt <=19'b0;
83 state <=?s2;
84 col <=4'b0111;???//消抖完表示按鍵有效
85 end
86 end
87 end
88 s2:begin
89 if(row !=4'b1111) //表示導(dǎo)通
90 begin
91 state <=?s3; ? //導(dǎo)通后跳轉(zhuǎn)下一個狀態(tài)
92 row_col <={row,col}; //拼接行和列信號
93 end
94 else //行信號不導(dǎo)通,開始進(jìn)行列掃描
95 begin
96 if(flag)
97 begin
98 col <={col[2:0],col[3]}; //1ms進(jìn)行一次列掃描
99 end
100 else
101 begin
102 col <=?col;
103 end
104 end
105 end
106 s3:begin
107 if(row ==4'b1111) //按鍵抬起
108 begin
109 state <=?s0;
110 data_flag <=1'b1; //表示一次成功的按鍵,輸出一個高脈沖
111 end
112 else
113 begin
114 state <=?s3;
115 end
116 end
117 default:state <=?s0;
118 endcase
119 end
120
121 reg[3:0]key_num;
122 //鍵值的翻譯模塊的表示
123 always@(posedgeclk ornegedgerst_n)
124 if(!rst_n)
125 key_num =4'd0;
126 else
127 case({row_col})
128 8'b0111_0111:key_num =4'hf;
129 8'b0111_1011:key_num =4'he;
130 8'b0111_1101:key_num =4'hd;
131 8'b0111_1110:key_num =4'hc;
132
133 8'b1011_0111:key_num =4'hb;
134 8'b1011_1011:key_num =4'ha;
135 8'b1011_1101:key_num =4'h9;
136 8'b1011_1110:key_num =4'h8;
137
138 8'b1101_0111:key_num =4'h7;
139 8'b1101_1011:key_num =4'h6;
140 8'b1101_1101:key_num =4'h5;
141 8'b1101_1110:key_num =4'h4;
142
143 8'b1110_0111:key_num =4'h3;
144 8'b1110_1011:key_num =4'h2;
145 8'b1110_1101:key_num =4'h1;
146 8'b1110_1110:key_num =4'h0;
147 default:;
148 endcase
149
150
151
152 //計算模塊的表示
153 reg[2:0]state_s;//狀態(tài)變量
154 reg[23:0]num1,num2,data_in,data_t; //信號變量
155 reg[3:0]flag_s;//運(yùn)算符
156 always@(posedgeclk ornegedgerst_n)
157 begin
158 if(!rst_n)
159 begin
160 data <=24'b0;
161 state_s <=?s0;
162 num1 <=24'b0;
163 num2 <=24'b0;
164 data_t <=24'b0;
165 flag_s <=4'b0;
166 data_in <=24'b0;
167 end
168 else
169 begin
170 case(state_s)
171 s0:begin
172 if(data_flag) //如果有一次按下
173 begin
174 if(key_num <4'd9)??//鍵值小于9便是有效
175 begin
176 num1 <=?num1*10+?key_num;??//BCD碼轉(zhuǎn)為2進(jìn)制
177 data <={data[19:0],key_num};??//數(shù)碼管移位
178 end
179 if(key_num >4'd9&&key_num <4'd14)//10 -- 13 表示運(yùn)算符
180 begin
181 data <=24'b0;
182 state_s <=?s1;
183 flag_s <=?key_num;
184 end
185 else//否則無效信號
186 state_s <=?s0;
187 end
188 end
189 s1:begin
190 if(data_flag)//如果有一次按下
191 begin
192 if(key_num <4'd9)??//鍵值小于9便是有效
193 begin
194 num2 <=10*num2 +key_num;//BCD碼轉(zhuǎn)為2進(jìn)制
195 data <={data[19:0],key_num};//數(shù)碼管移位
196 end
197 if(key_num >4'd9&&key_num <4'd14)//10 -- 13 表示運(yùn)算符
198 begin
199 state_s <=?s1;
200 end
201 if(key_num ==15)//表示等于
202 begin
203 state_s <=?s2;
204 end
205 end
206 end
207 s2:begin
208 state_s <=?s3;
209 case(flag_s)
210
211 4'd10:begin//加運(yùn)算
212 data_in <=?num1 +?num2;??
213 state_s <=?s3;
214 end
215
216 4'd13:begin//乘運(yùn)算
217 data_in <=?num1 *?num2;
218 state_s <=?s3;
219 end
220 endcase
221 end
222 s3:begin//二進(jìn)制轉(zhuǎn)為BCD碼顯示到對應(yīng)的數(shù)碼管上
223 data[3:0]=data_in %10;
224 data[7:4]=data_in /10%10;
225 data[11:8]=data_in /100%10;
226 data[15:12]=data_in /1000%10;
227 data[19:16]=data_in /10000%10;
228 data[23:20]=data_in /100000;
229 state_s <=?s0;
230 data_in <=24'b0;
231 end
232 default:state_s <=?s0;
233 endcase
234 end
235 end
236
237
258endmodule
測試模塊
0`timescale1ns/1ps
1
2modulecalc_tb();
3 regclk;
4 regrst_n;
5 reg[4:0]pressnum;
6 wire[3:0]row;
7
8 wire[3:0]col;
9 wire[3:0]key_num;
10
11 initialbegin
12 clk =1'b1;
13 rst_n =1'b0;
14 pressnum =5'd16;
15
16 #200.1
17 rst_n =1'b1;
18 #2000
19 pressnum =5'd16;
20
21 #1000
22 pressnum =5'd5;
23
24 #1000
25 pressnum =5'd16;
26
27 #1250
28 pressnum =5'd11;
29 #1250
30 pressnum =5'd16;
31 #1250
32 pressnum =5'd2;
33 #1250
34 pressnum =5'd16;
35 #1250
36 pressnum =5'd15;
37 #1250
38 pressnum =5'd16;
39 #2000
40 #2000
41 $stop;
42
43 end
44 always#10clk =~clk;
45
46 calc calc_dut(
47 .clk(clk),
48 .rst_n(rst_n),
49 .row(row),
50 .col(col),
51 .sel(sel),
52 .seg7(seg7)
53 );
54 yingjian yingjian_dut(
55 .clk(clk),
56 .rst_n(rst_n),
57 .col(col),
58 .row(row),
59 .pressnum(pressnum)
60 );
61endmodule
仿真圖:
從仿真圖中可以看出,在放著中我們設(shè)置的是先按下5,再10,之后2,然后按下等于15.通過觀察仿真正確,之后由于設(shè)計中我們10是表示加法,那么5 + 2 = 7 :結(jié)果顯示正確。
-
FPGA
+關(guān)注
關(guān)注
1630文章
21796瀏覽量
605987 -
數(shù)碼管
+關(guān)注
關(guān)注
32文章
1887瀏覽量
91402 -
計算器
+關(guān)注
關(guān)注
16文章
438瀏覽量
37469
原文標(biāo)題:FPGA學(xué)習(xí)系列:29. 計算器的設(shè)計
文章出處:【微信號:FPGAer_Club,微信公眾號:FPGAer俱樂部】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論