源自http://www.cnblogs.com/oomusou/archive/2008/07/31/verilog_digi_clock2.html
如何設計電子鐘(II)
Abstract
之前曾完全使用Verilog的RTL撰寫一個電子鐘((原創) 如何設計電子鐘(I)? (SOC) (Verilog) (DE2)),這次功能一樣,但使用Altera所提供的Mega function:lpm_counter()與lpm_ff()來實現。
之前曾完全使用Verilog的RTL撰寫一個電子鐘((原創) 如何設計電子鐘(I)? (SOC) (Verilog) (DE2)),這次功能一樣,但使用Altera所提供的Mega function:lpm_counter()與lpm_ff()來實現。
Introduction
使用環境:Quartus II 7.2 SP3 + DE2(Cyclone II EP2C35F627C6)
使用環境:Quartus II 7.2 SP3 + DE2(Cyclone II EP2C35F627C6)
在(原創) 如何設計電子鐘(I)? (SOC) (Verilog) (DE2)中,我們全部自己來,從除頻器到計數器通通自己來。這次我們用的是Altera所提供的Mega function。
digi_clock2.v / Verilog
1 /* 2 (C) OOMusou 2008 http://oomusou.cnblogs.com
3
4 Filename : digi_clock2.v 5 Compiler : Quartus II 7.2 SP3 + ModelSim-Altera 6.1g 6 Description : Demo how to write clock counter 7 Release : 07/31/2008 1.0 8 */
9 module digi_clock2 (10 input CLOCK_50,11 input [17:0] SW,12 input [3:0] KEY,13 output [6:0] HEX2,14 output [6:0] HEX3,15 output [6:0] HEX4,16 output [6:0] HEX5,17 output [6:0] HEX6,18 output [6:0] HEX719 );20
21 wire clk; // 1 Hz clock
22 wire en; // counter enable
23 wire clr; // counter clear
24 wire load; // load new min & hour
25 wire co; // carry out for 23:59:59
26 wire [3:0] md0; // original input for min[0]
27 wire [2:0] md1; // original input for min[1]
28 wire [3:0] hd0; // original input for hour[0]
29 wire [2:0] hd1; // original input for hour[1]
30
31 wire w_clk; // temp clk for lpm_counter
32 wire [3:0] w_md0; // correct input for min[0]
33 wire [2:0] w_md1; // correct input for min[1]
34 reg [3:0] w_hd0; // correct input for hour[0]
35 reg [2:0] w_hd1; // correct input for hour[1]
36 wire [3:0] w_sq0; // correct output for sec[0]
37 wire [2:0] w_sq1; // correct output for sec[1]
38 wire [3:0] w_mq0; // corrent output for min[0]
39 wire [2:0] w_mq1; // correct output for min[1]
40 wire [3:0] w_hq0; // correct output for hour[0]
41 wire [2:0] w_hq1; // correct output for hour[1]
42
43 wire w_co_sq0; // carry out for sec[0]
44 wire w_co_sq1; // carry out for sec[1]
45 wire w_co_mq0; // carry out for min[0]
46 wire w_co_mq1; // carry out for min[1]
47 wire w_co_hq0; // carry out for hour[0]
48 wire w_co_hq1; // carry out for hour[1]
49
50 assign en = SW[17];51 assign clr = SW[16] | co;52 assign load = SW[15];53 assign md0 = SW[3:0];54 assign md1 = SW[6:4];55 assign hd0 = SW[10:7];56 assign hd1 = SW[13:11];57
58 assign w_md0 = (!load) ? 0 :59 (md0 < 10) ? md0 : 9;60 assign w_md1 = (!load) ? 0 : 61 (md1 < 6) ? md1 : 5;62 63 // 23:59:59
64 /*
65 assign co = ~ load 66 & w_hq1[1] // 267 & w_hq0[1] & w_hq0[0] // 368 & w_mq1[2] & w_mq1[0] // 569 & w_mq0[3] & w_mq0[0] // 970 & w_sq1[2] & w_sq0[0] // 571 & w_sq0[2] & w_sq0[0]; // 972 */
73 assign co = w_co_sq1 & w_co_mq1 & w_co_hq1 74 & w_hq0[1] & w_hq0[0]; // 3 75
76 // 1Hz --------------------
77 lpm_counter # (78 .lpm_width(25),79 .lpm_direction("UP"),80 .lpm_modulus(50000000>>1)81 ) u0 (82 .clock(CLOCK_50),83 .cout(w_clk)84 );85
86 lpm_ff # (87 .lpm_width(1),88 .lpm_fftype("TFF")89 )90 u1 (91 .clock(CLOCK_50),92 .data(w_clk),93 .q(clk)94 );95 // -----------------------96
97 // sec[0].-------------------
98 lpm_counter # (99 .lpm_width(4),100 .lpm_direction("UP"),101 .lpm_modulus(10)102 ) u2 (103 .cnt_en(en),104 .sclr(clr),105 .clock(clk),106 .sload(load),107 .data(4'h0),
108 .q(w_sq0),109 .cout(w_co_sq0)110 );111 // -----------------------112
113 // sec[1].-------------------
114 lpm_counter # (115 .lpm_width(3),116 .lpm_direction("UP"),117 .lpm_modulus(6)118 ) u3 (119 .cnt_en(en & w_co_sq0),120 .sclr(clr),121 .clock(clk),122 .sload(load),123 .data(3'h0),
124 .q(w_sq1),125 .cout(w_co_sq1)126 );127 // -----------------------128
129 // min[0].-------------------
130 lpm_counter # (131 .lpm_width(4),132 .lpm_direction("UP"),133 .lpm_modulus(10)134 ) u4 (135 .cnt_en(en & w_co_sq1 & w_co_sq0),136 .sclr(clr),137 .clock(clk),138 .sload(load),139 .data(w_md0),140 .q(w_mq0),141 .cout(w_co_mq0)142 );143 // -----------------------144
145 // min[1].-------------------
146 lpm_counter # (147 .lpm_width(3),148 .lpm_direction("UP"),149 .lpm_modulus(6)150 ) u5 (151 .cnt_en(en & w_co_mq0 & w_co_sq1 & w_co_sq0),152 .sclr(clr),153 .clock(clk),154 .sload(load),155 .data(w_md1),156 .q(w_mq1),157 .cout(w_co_mq1)158 );159 // -----------------------160
161 // hour[0].-------------------
162 lpm_counter # (163 .lpm_width(4),164 .lpm_direction("UP"),165 .lpm_modulus(10)166 ) u6 (167 .cnt_en(en & w_co_mq1 & w_co_mq0 & w_co_sq1 & w_co_sq0),168 .sclr(clr),169 .clock(clk),170 .sload(load),171 .data(w_hd0),172 .q(w_hq0),173 .cout(w_co_hq0)174 );175 // -----------------------176
177 // hour[1].-------------------
178 lpm_counter # (179 .lpm_width(2),180 .lpm_direction("UP"),181 .lpm_modulus(3)182 ) u7 (183 .cnt_en(en & w_co_hq0 & w_co_mq1 & w_co_mq0 & w_co_sq1 & w_co_sq0),184 .sclr(clr),185 .clock(clk),186 .sload(load),187 .data(w_hd1),188 .q(w_hq1),189 .cout(w_co_hq1)190 );191 // -----------------------192
193 // sec. dig0 to seg7
194 seg7_lut u8 (195 .i_dig(w_sq0),196 .o_seg(HEX2)197 );198
199 // sec. dig1 to seg7
200 seg7_lut u9 (201 .i_dig({1'b0, w_sq1}),
202 .o_seg(HEX3)203 );204
205 // min. dig0 to seg7
206 seg7_lut u10 (207 .i_dig(w_mq0),208 .o_seg(HEX4)209 );210
211 // min. dig1 to seg7
212 seg7_lut u11 (213 .i_dig({1'b0, w_mq1}),
214 .o_seg(HEX5)215 );216
217 // hour dig0 to seg7
218 seg7_lut u12 (219 .i_dig(w_hq0),220 .o_seg(HEX6)221 );222
223 // hour dig1 to seg7
224 seg7_lut u13 (225 .i_dig({1'b0, w_hq1}),
226 .o_seg(HEX7)227 );228
229 always@(load, hd0, hd1) begin
230 if (!load) begin
231 w_hd0 = 0;232 w_hd1 = 0;233 end
234 else begin
235 if (hd1 <= 1) begin // 0 1
236 w_hd1 = hd1;237 238 if (hd0 < 10)239 w_hd0 = hd0;240 else
241 w_hd0 = 9;242 end
243 else begin // >= 2
244 w_hd1 = 2;245 246 if (hd0 < 4)247 w_hd0 = hd0;248 else
249 w_hd0 = 3;250 end
251 end
252 end 253
254 endmodule
3
4 Filename : digi_clock2.v 5 Compiler : Quartus II 7.2 SP3 + ModelSim-Altera 6.1g 6 Description : Demo how to write clock counter 7 Release : 07/31/2008 1.0 8 */
9 module digi_clock2 (10 input CLOCK_50,11 input [17:0] SW,12 input [3:0] KEY,13 output [6:0] HEX2,14 output [6:0] HEX3,15 output [6:0] HEX4,16 output [6:0] HEX5,17 output [6:0] HEX6,18 output [6:0] HEX719 );20
21 wire clk; // 1 Hz clock
22 wire en; // counter enable
23 wire clr; // counter clear
24 wire load; // load new min & hour
25 wire co; // carry out for 23:59:59
26 wire [3:0] md0; // original input for min[0]
27 wire [2:0] md1; // original input for min[1]
28 wire [3:0] hd0; // original input for hour[0]
29 wire [2:0] hd1; // original input for hour[1]
30
31 wire w_clk; // temp clk for lpm_counter
32 wire [3:0] w_md0; // correct input for min[0]
33 wire [2:0] w_md1; // correct input for min[1]
34 reg [3:0] w_hd0; // correct input for hour[0]
35 reg [2:0] w_hd1; // correct input for hour[1]
36 wire [3:0] w_sq0; // correct output for sec[0]
37 wire [2:0] w_sq1; // correct output for sec[1]
38 wire [3:0] w_mq0; // corrent output for min[0]
39 wire [2:0] w_mq1; // correct output for min[1]
40 wire [3:0] w_hq0; // correct output for hour[0]
41 wire [2:0] w_hq1; // correct output for hour[1]
42
43 wire w_co_sq0; // carry out for sec[0]
44 wire w_co_sq1; // carry out for sec[1]
45 wire w_co_mq0; // carry out for min[0]
46 wire w_co_mq1; // carry out for min[1]
47 wire w_co_hq0; // carry out for hour[0]
48 wire w_co_hq1; // carry out for hour[1]
49
50 assign en = SW[17];51 assign clr = SW[16] | co;52 assign load = SW[15];53 assign md0 = SW[3:0];54 assign md1 = SW[6:4];55 assign hd0 = SW[10:7];56 assign hd1 = SW[13:11];57
58 assign w_md0 = (!load) ? 0 :59 (md0 < 10) ? md0 : 9;60 assign w_md1 = (!load) ? 0 : 61 (md1 < 6) ? md1 : 5;62 63 // 23:59:59
64 /*
65 assign co = ~ load 66 & w_hq1[1] // 267 & w_hq0[1] & w_hq0[0] // 368 & w_mq1[2] & w_mq1[0] // 569 & w_mq0[3] & w_mq0[0] // 970 & w_sq1[2] & w_sq0[0] // 571 & w_sq0[2] & w_sq0[0]; // 972 */
73 assign co = w_co_sq1 & w_co_mq1 & w_co_hq1 74 & w_hq0[1] & w_hq0[0]; // 3 75
76 // 1Hz --------------------
77 lpm_counter # (78 .lpm_width(25),79 .lpm_direction("UP"),80 .lpm_modulus(50000000>>1)81 ) u0 (82 .clock(CLOCK_50),83 .cout(w_clk)84 );85
86 lpm_ff # (87 .lpm_width(1),88 .lpm_fftype("TFF")89 )90 u1 (91 .clock(CLOCK_50),92 .data(w_clk),93 .q(clk)94 );95 // -----------------------96
97 // sec[0].-------------------
98 lpm_counter # (99 .lpm_width(4),100 .lpm_direction("UP"),101 .lpm_modulus(10)102 ) u2 (103 .cnt_en(en),104 .sclr(clr),105 .clock(clk),106 .sload(load),107 .data(4'h0),
108 .q(w_sq0),109 .cout(w_co_sq0)110 );111 // -----------------------112
113 // sec[1].-------------------
114 lpm_counter # (115 .lpm_width(3),116 .lpm_direction("UP"),117 .lpm_modulus(6)118 ) u3 (119 .cnt_en(en & w_co_sq0),120 .sclr(clr),121 .clock(clk),122 .sload(load),123 .data(3'h0),
124 .q(w_sq1),125 .cout(w_co_sq1)126 );127 // -----------------------128
129 // min[0].-------------------
130 lpm_counter # (131 .lpm_width(4),132 .lpm_direction("UP"),133 .lpm_modulus(10)134 ) u4 (135 .cnt_en(en & w_co_sq1 & w_co_sq0),136 .sclr(clr),137 .clock(clk),138 .sload(load),139 .data(w_md0),140 .q(w_mq0),141 .cout(w_co_mq0)142 );143 // -----------------------144
145 // min[1].-------------------
146 lpm_counter # (147 .lpm_width(3),148 .lpm_direction("UP"),149 .lpm_modulus(6)150 ) u5 (151 .cnt_en(en & w_co_mq0 & w_co_sq1 & w_co_sq0),152 .sclr(clr),153 .clock(clk),154 .sload(load),155 .data(w_md1),156 .q(w_mq1),157 .cout(w_co_mq1)158 );159 // -----------------------160
161 // hour[0].-------------------
162 lpm_counter # (163 .lpm_width(4),164 .lpm_direction("UP"),165 .lpm_modulus(10)166 ) u6 (167 .cnt_en(en & w_co_mq1 & w_co_mq0 & w_co_sq1 & w_co_sq0),168 .sclr(clr),169 .clock(clk),170 .sload(load),171 .data(w_hd0),172 .q(w_hq0),173 .cout(w_co_hq0)174 );175 // -----------------------176
177 // hour[1].-------------------
178 lpm_counter # (179 .lpm_width(2),180 .lpm_direction("UP"),181 .lpm_modulus(3)182 ) u7 (183 .cnt_en(en & w_co_hq0 & w_co_mq1 & w_co_mq0 & w_co_sq1 & w_co_sq0),184 .sclr(clr),185 .clock(clk),186 .sload(load),187 .data(w_hd1),188 .q(w_hq1),189 .cout(w_co_hq1)190 );191 // -----------------------192
193 // sec. dig0 to seg7
194 seg7_lut u8 (195 .i_dig(w_sq0),196 .o_seg(HEX2)197 );198
199 // sec. dig1 to seg7
200 seg7_lut u9 (201 .i_dig({1'b0, w_sq1}),
202 .o_seg(HEX3)203 );204
205 // min. dig0 to seg7
206 seg7_lut u10 (207 .i_dig(w_mq0),208 .o_seg(HEX4)209 );210
211 // min. dig1 to seg7
212 seg7_lut u11 (213 .i_dig({1'b0, w_mq1}),
214 .o_seg(HEX5)215 );216
217 // hour dig0 to seg7
218 seg7_lut u12 (219 .i_dig(w_hq0),220 .o_seg(HEX6)221 );222
223 // hour dig1 to seg7
224 seg7_lut u13 (225 .i_dig({1'b0, w_hq1}),
226 .o_seg(HEX7)227 );228
229 always@(load, hd0, hd1) begin
230 if (!load) begin
231 w_hd0 = 0;232 w_hd1 = 0;233 end
234 else begin
235 if (hd1 <= 1) begin // 0 1
236 w_hd1 = hd1;237 238 if (hd0 < 10)239 w_hd0 = hd0;240 else
241 w_hd0 = 9;242 end
243 else begin // >= 2
244 w_hd1 = 2;245 246 if (hd0 < 4)247 w_hd0 = hd0;248 else
249 w_hd0 = 3;250 end
251 end
252 end 253
254 endmodule
76行
// 1Hz --------------------
lpm_counter # (
.lpm_width(25),
.lpm_direction("UP"),
.lpm_modulus(50000000>>1)
) u0 (
.clock(CLOCK_50),
.cout(w_clk)
);
lpm_ff # (
.lpm_width(1),
.lpm_fftype("TFF")
)
u1 (
.clock(CLOCK_50),
.data(w_clk),
.q(clk)
);// -----------------------
lpm_counter # (
.lpm_width(25),
.lpm_direction("UP"),
.lpm_modulus(50000000>>1)
) u0 (
.clock(CLOCK_50),
.cout(w_clk)
);
lpm_ff # (
.lpm_width(1),
.lpm_fftype("TFF")
)
u1 (
.clock(CLOCK_50),
.data(w_clk),
.q(clk)
);// -----------------------
使用lpm_counter + lpm_ff的T-FF來實現1 Hz的clock,請參閱(原創) 如何設計除頻器? (SOC) (Verilog) (MegaCore) 。
97行
// sec[0].-------------------
lpm_counter # (
.lpm_width(4),
.lpm_direction("UP"),
.lpm_modulus(10)
) u2 (
.cnt_en(en),
.sclr(clr),
.clock(clk),
.sload(load),
.data(4'h0),
.q(w_sq0),
.cout(w_co_sq0)
);// -----------------------
lpm_counter # (
.lpm_width(4),
.lpm_direction("UP"),
.lpm_modulus(10)
) u2 (
.cnt_en(en),
.sclr(clr),
.clock(clk),
.sload(load),
.data(4'h0),
.q(w_sq0),
.cout(w_co_sq0)
);// -----------------------
在(原創) 如何設計電子鐘(I)? (SOC) (Verilog) (DE2),對於秒方面是自己寫的60計數器, 在這裏我們是一個位數一個位數的處理,由於分最多是59秒,也就是說,秒的個位數需要的是10計數器。計數器請參閱(筆記) 如何設計計數器? (SOC) (Verilog) (MegaCore)。
113行
// sec[1].-------------------
lpm_counter # (
.lpm_width(3),
.lpm_direction("UP"),
.lpm_modulus(6)
) u3 (
.cnt_en(en & w_co_sq0),
.sclr(clr),
.clock(clk),
.sload(load),
.data(3'h0),
.q(w_sq1),
.cout(w_co_sq1)
);// -----------------------
lpm_counter # (
.lpm_width(3),
.lpm_direction("UP"),
.lpm_modulus(6)
) u3 (
.cnt_en(en & w_co_sq0),
.sclr(clr),
.clock(clk),
.sload(load),
.data(3'h0),
.q(w_sq1),
.cout(w_co_sq1)
);// -----------------------
同理,秒的十位數需要的是一個6計數器。由於十位數是由個位數所進位,所以counter的enable由en與個位數的進位w_co_sq0共同決定。至於時與分,道理相同,我就不再多言。
63行
// 23:59:59
assign co = ~ load
& w_hq1[1] // 2
& w_hq0[1] & w_hq0[0] // 3
& w_mq1[2] & w_mq1[0] // 5
& w_mq0[3] & w_mq0[0] // 9
& w_sq1[2] & w_sq0[0] // 5
& w_sq0[2] & w_sq0[0]; // 9
assign co = ~ load
& w_hq1[1] // 2
& w_hq0[1] & w_hq0[0] // 3
& w_mq1[2] & w_mq1[0] // 5
& w_mq0[3] & w_mq0[0] // 9
& w_sq1[2] & w_sq0[0] // 5
& w_sq0[2] & w_sq0[0]; // 9
到23:59:59會歸00:00:00,這裡有兩種做法,一種是判斷都23:59:59時進位。且特意的避開load。
73行
assign co = w_co_sq1 & w_co_mq1 & w_co_hq1
& w_hq0[1] & w_hq0[0]; // 3
& w_hq0[1] & w_hq0[0]; // 3
這種方式與(原創) 如何設計電子鐘(I)? (SOC) (Verilog) (DE2)較類似,判斷時、分、秒十位數部分是否進位,但因為時是24小時進位, 還要確定時的個位是否為3才能進位。
58行
assign w_md0 = (!load) ? 0 :
(md0 < 10) ? md0 : 9;assign w_md1 = (!load) ? 0 :
(md1 < 6) ? md1 : 5;
(md0 < 10) ? md0 : 9;assign w_md1 = (!load) ? 0 :
(md1 < 6) ? md1 : 5;
229行
always@(load, hd0, hd1) begin
if (!load) begin
w_hd0 = 0;
w_hd1 = 0;
end
else begin
if (hd1 <= 1) begin // 0 1
w_hd1 = hd1;
if (hd0 < 10)
w_hd0 = hd0;
else
w_hd0 = 9;
end
else begin // >= 2
w_hd1 = 2;
if (hd0 < 4)
w_hd0 = hd0;
else
w_hd0 = 3;
end
end
end
if (!load) begin
w_hd0 = 0;
w_hd1 = 0;
end
else begin
if (hd1 <= 1) begin // 0 1
w_hd1 = hd1;
if (hd0 < 10)
w_hd0 = hd0;
else
w_hd0 = 9;
end
else begin // >= 2
w_hd1 = 2;
if (hd0 < 4)
w_hd0 = hd0;
else
w_hd0 = 3;
end
end
end
都只是為了輸入防呆,在(原創) 如何設計除頻器? (SOC) (Verilog) (MegaCore)都曾經討論過,只是將code搬過來而已。
完整程式碼下載
digi_clock2.7z
digi_clock2.7z
Conclusion
其實也不一定得用Mega function不可,只是趁機熟悉一下Mega function的使用方法。Mega function類似C++的STL,用STL會使程式短一點,但你要用C++自己實做演算法當然也可以。
其實也不一定得用Mega function不可,只是趁機熟悉一下Mega function的使用方法。Mega function類似C++的STL,用STL會使程式短一點,但你要用C++自己實做演算法當然也可以。
沒有留言:
張貼留言