功能描述:按4*4键盘上的1,2,3...号按键可依次测出 25000000Hz ,12500000Hz ....的分频信号并显示在8个数码管上. 希望和初学者一起学习 163haole@163.com 本设计由以下四个模块组成. freqtest.v -8位十进制频率计 (顶层模块) KeyBoard.v -4*4键盘扫描模块 (选择不同的被测信号) cnt10.v -十进制计数器模块 (测频计数) scan_led.v -数码管动态扫描模块 (显示测量结果)
/* freqtest.v -8位十进制频率计*/
/* Copyright 2008-2018 */
/* modification history -------------------- 01a,16jan08,52mcu 163haole@163.com */
/* DESCRIPTION Cyclone II EP2C5Q208C
*/ module freqtest(clock,freq_input,dig,seg,test,col,row,rstkey); input clock; //系统时钟 inout freq_input; //被测信号时钟 output[2:0] dig; //数码管选择输出 output[7:0] seg; //数码管段输出引脚 output[9:0] test;//输出频率信号,用于测试
output [3:0] col ; input [3:0] row ; input rstkey ;
reg[25:0]counter; //时钟分频计数器 reg[31:0]freq_result; //频率测量结果寄存器 wire [31:0]pre_freq; //脉冲计数寄存器 reg rst; wire divide_clk; //1Hz闸门信号 wire clk_scan; //数码管扫描时钟 wire cout1,cout2,cout3,cout4,cout5,cout6,cout7;
assign clk_scan = counter[15]; //动态扫描时钟 assign test = counter[9:0];//输出频率信号,用于测试
reg [31:0] Mega_cnt; reg[3:0]key; reg freq_input_r;
//时钟分频进程:分出1hz基准信号 always @(posedge clock) begin if(divide_clk) counter<=26'd0; else counter<=counter+1'b1; end
assign divide_clk=(counter>=26'd50000000);//
//锁存测量值进程 always @(posedge clock) begin if(divide_clk) freq_result<=pre_freq; end
//产生计数器复信号 always @(posedge clock) begin if(divide_clk) rst<=1'b1; else rst<=1'b0; end
//产生被测频率信号
//assign freq_input=counter[1]; assign freq_input= freq_input_r;
always @(posedge clock ) //sys_clk 50Mhz begin
if(Mega_cnt>32'd48) //50-2 begin Mega_cnt<=32'd0; end else Mega_cnt<=Mega_cnt+1; end
assign clk_1Mhz = Mega_cnt[5];//1Mhz
KeyBoard (.code(key),.col(col),.valid(valid),.row(row),.sys_clk(clk_1Mhz),.rst(rstkey));
always @(key) begin case(key) 4'd1: freq_input_r=counter[0];//25000000 4'd2: freq_input_r=counter[1]; 4'd3: freq_input_r=counter[2]; 4'd4: freq_input_r=counter[3]; 4'd5: freq_input_r=counter[4]; 4'd6: freq_input_r=counter[5]; 4'd7: freq_input_r=counter[6]; 4'd8: freq_input_r=counter[7]; 4'd9: freq_input_r=counter[8]; 4'd10:freq_input_r=counter[9]; 4'd11:freq_input_r=counter[10]; 4'd12:freq_input_r=counter[11]; 4'd13:freq_input_r=counter[12]; 4'd14:freq_input_r=counter[13]; 4'd15:freq_input_r=counter[14]; 4'd0:freq_input_r=counter[15]; //762.939453125Hz default:freq_input_r=counter[0]; endcase
end
//8位十进制模块:由8个十进制计数模块构成 //* cnt10 u1(.clock(freq_input),.rst(rst),.cin(1'b1), .cout(cout1),.dout(pre_freq[3:0])); cnt10 u2(.clock(freq_input),.rst(rst),.cin(cout1),.cout(cout2),.dout(pre_freq[7:4])); cnt10 u3(.clock(freq_input),.rst(rst),.cin(cout2),.cout(cout3),.dout(pre_freq[11:8])); cnt10 u4(.clock(freq_input),.rst(rst),.cin(cout3),.cout(cout4),.dout(pre_freq[15:12])); cnt10 u5(.clock(freq_input),.rst(rst),.cin(cout4),.cout(cout5),.dout(pre_freq[19:16])); cnt10 u6(.clock(freq_input),.rst(rst),.cin(cout5),.cout(cout6),.dout(pre_freq[23:20])); cnt10 u7(.clock(freq_input),.rst(rst),.cin(cout6),.cout(cout7),.dout(pre_freq[27:24])); cnt10 u8(.clock(freq_input),.rst(rst),.cin(cout7),.cout(), .dout(pre_freq[31:28])); //*/ //数码管显示模块 scan_led u9(.clk_1k(clk_scan),.d(freq_result),.dig(dig),.seg(seg));
endmodule
/* KeyBoard.v -4*4键盘扫描模块*/
/* Copyright 2008-2018 */
/* modification history -------------------- 01a,20jan08,52mcu modified comment 163haole@163.com 01a,13jan08,52mcu added comment */
/* DESCRIPTION Cyclone II EP2C5Q208C
*/ module KeyBoard( code , col , valid , row , sys_clk , rst ); output [3:0] col ; output valid ; output [3:0] code ; input [3:0] row ; input sys_clk,rst ; reg [3:0] col,code; reg [5:0] state,next_state; parameter S_0 = 6'b000001, S_1 = 6'b000010, S_2 = 6'b000100, S_3 = 6'b001000, S_4 = 6'b010000, S_5 = 6'b100000; reg S_row ; reg [3:0] count,row_reg,col_reg; reg clk2,clk4; reg [24:0] Mega_cnt; wire clk; /**************************************/ always @(posedge sys_clk or negedge rst) //sys_clk 1Mhz begin if(!rst) begin Mega_cnt<=0; end else begin Mega_cnt<=Mega_cnt+1; end end
assign clk = Mega_cnt[4]; //clk 1Mhz/2^(4+1)=31.25Khz /**************************************/ always @ (posedge clk) //clk2 clk/2=62.5Khz/2=15.625Khz clk2 <= ~clk2; always @ (posedge clk2) //clk4 clk2/2=15.625Khz/2=7.8125Khz 0.128ms clk4 <= ~clk4; always @ (posedge clk4 or negedge rst) if(!rst) begin count <= 0; S_row <= 0; end else begin if(!(row[0]&row[1]&row[2]&row[3])) begin if(count < 'd4) count <= count +1 ; else S_row <= 1; end else if(state[5]||state[0]) begin count <= 0; S_row <= 0; end end assign valid = ((state == S_1)||(state == S_2)||(state == S_3)||(state == S_4)) && (!(row[3]&row[2]&row[1]&row[0])) ; always @ (negedge clk) //clk 1Mhz/2^(4+1)=31.25Khz if(valid) begin row_reg <= row ; col_reg <= col ; end else begin row_reg <= row_reg ; col_reg <= col_reg ; end always @ (row_reg or col_reg or clk) case({row_reg,col_reg}) 8'b1110_1110: code = 13; 8'b1110_1101: code = 9 ; 8'b1110_1011: code = 5 ; 8'b1110_0111: code = 1 ; 8'b1101_1110: code = 14; 8'b1101_1101: code = 10; 8'b1101_1011: code = 6 ; 8'b1101_0111: code = 2 ; 8'b1011_1110: code = 15 ; 8'b1011_1101: code = 11 ; 8'b1011_1011: code = 7; 8'b1011_0111: code = 3; 8'b0111_1110: code = 0; 8'b0111_1101: code = 12; 8'b0111_1011: code = 8; 8'b0111_0111: code = 4; endcase always @ (posedge clk4 or negedge rst) //clk4 clk2/2=15.625Khz/2=7.8125Khz 0.128ms if(!rst) state <= S_0 ; else state <= next_state ; always @ ( state or row or S_row) begin // next_state = state ; col =0; case(state) S_0 : begin col = 4'b0000; if(S_row) next_state = S_1; else next_state = S_0; end S_1 : begin col = 4'b1110; if(row!='hf) next_state = S_5; else next_state = S_2; end S_2 : begin col = 4'b1101; if(row!='hf) next_state = S_5; else next_state = S_3; end S_3 : begin col = 4'b1011; if(row!='hf) next_state = S_5; else next_state = S_4; end S_4 : begin col = 4'b0111; if(row!='hf) next_state = S_5; else next_state = S_0; end S_5 : begin col = 4'b0000; if(row == 4'b1111) next_state = S_0; else next_state = S_5; end default: next_state = S_0; endcase end endmodule
/* cnt10.v -十进制计数器*/
/* Copyright 2008-2018 */
/* modification history -------------------- 01a,16jan08,52mcu 163haole@163.com */
/* DESCRIPTION Cyclone II EP2C5Q208C
*/ module cnt10(clock,rst,cin,cout,dout);//十进制计数器 input clock;//计数时钟 input cin;//进位输入 input rst;// 复位信号 output cout;//进位输出 output[3:0]dout;//计数输出 reg[3:0]counter; //寄存器 assign dout=counter;
assign cout=cin&&(counter>=4'd9); //进位输出 always @(posedge clock or posedge rst) begin if(rst) counter<=4'd0;//计数器复位 else if(cin) //进位输入 begin if(cout) counter<=4'd0; else counter<=counter+1'b1; end end endmodule
/* scan_led.v -数码管动态扫描 */
/* Copyright 2008-2018 */
/* modification history -------------------- 01a 15jan08 52mcu solve the dig problem 163haole@163.com 01a,10jan08,52mcu */
/* DESCRIPTION Cyclone II EP2C5Q208C
*/
module scan_led(clk_1k,d,dig,seg); input clk_1k; input[31:0]d;
output[2:0]dig; output[7:0]seg;
reg[7:0]seg_r; reg[2:0]dig_r; reg[3:0]disp_dat; reg[2:0]count;
assign dig=dig_r; assign seg = seg_r;
always @(posedge clk_1k) begin count<=count+1'b1; end
always @(posedge clk_1k) begin case(count) 3'd0:disp_dat=d[31:28]; 3'd1:disp_dat=d[27:24]; 3'd2:disp_dat=d[23:20]; 3'd3:disp_dat=d[19:16]; 3'd4:disp_dat=d[15:12]; 3'd5:disp_dat=d[11:8]; 3'd6:disp_dat=d[7:4]; 3'd7:disp_dat=d[3:0]; endcase dig_r = count; end always @(disp_dat) begin case(disp_dat) 4'h0:seg_r = 8'b00111111;// '0'8'b00000001;// '-' 4'h1:seg_r = 8'b00000110;// '1' 4'h2:seg_r = 8'b01011011;// '2' 4'h3:seg_r = 8'b01001111;// '3' 4'h4:seg_r = 8'b01100110;// '4' 4'h5:seg_r = 8'b01101101;// '5' 4'h6:seg_r = 8'b01111101;// '6' 4'h7:seg_r = 8'b00000111;// '7' 4'h8:seg_r = 8'b01111111;// '8' 4'h9:seg_r = 8'b01101111;// '9' 4'ha:seg_r = 8'b01110111;// 'a' 4'hb:seg_r = 8'b01111100;// 'b' 4'hc:seg_r = 8'b00111001;// 'c' 4'hd:seg_r = 8'b01011110;// 'd' 4'he:seg_r = 8'b01111001;// 'e' 4'hf:seg_r = 8'b01110001;// 'f' endcase end endmodule
|