module bell
(
clk,
rst,
Bell,
data_1
);
input clk,rst;
output Bell;
reg Bell;
reg [15:0] Cnt;
reg [15:0] PreDiv;//每个音调需要分频的系数
input [3:0] data_1;
defparam Gen_ClkBell.divdWIDTH=2,Gen_ClkBell.divdFACTOR=2;//4分频,得到12M时钟
gen_divd Gen_ClkBell(.reset(Resetb),.clkin(ClkIn),.clkout(ClkBell));
//always @ (negedge rst or posedge ClkBell)
// if(!Resetb)
// begin
// Bell=1'b0;
// data_1=0;
// PreDiv<=16'h0;//没声
// end
// else
begin
Bell<=~Bell;
case(data_1) //进行音调的切换
1:PreDiv<=16'h5997;//1
2:PreDiv<=16'h4FCD;//2
3:PreDiv<=16'h471B;//3
4:PreDiv<=16'h431E;//4
endcase
end
endmodule
报错
Error (10170): Verilog HDL syntax error at bell.v(28) near text "begin"; expecting "endmodule"
Error (10112): Ignored design unit "bell" at bell.v(2) due to previous errors
//偶数分频器,外部带入两个参数决定分频系数。默认是2分频
//divdFACTOR--分频系数,实际分频数为divdFACTOR*2
//divdWIDTH--分频计数器的位宽,实际位宽为divdWIDTH+1,该位宽所能表达的最大值>divdFACTOR
module gen_divd(reset,clkin,clkout);
input reset,clkin;
output clkout;
parameter divdWIDTH=1;//分频计数器的位宽,实际位宽为divdWIDTH+1,该位宽所能表达的最大值>divdFACTOR
parameter divdFACTOR=1;//分频系数是divdFACTOR*2
reg clkout;
reg [divdWIDTH:0] cnt;
always @ (negedge reset or posedge clkin)
if(reset==1'b0)
begin
cnt=0;
clkout=0;
end
else
begin
cnt=cnt+1'b1;//常数1要指定位数,否则默认是32位的
if(cnt>=divdFACTOR)
begin
cnt=0;
clkout=~clkout;
end
end
endmodule
//矩阵键盘扫描 并将键值送出
module matrix_key
(
clk, //48MHZ
reset,
col, //列
row, //行
data_1,//键值,个位
data_10,//十位
data_100,//百位
data_1000 //千位
);
input clk,reset;
input [1:0] col;
output [1:0] row;
output [3:0] data_1,data_10,data_100,data_1000;
reg [1:0] row;
reg [3:0] data_1,data_10,data_100,data_1000;
reg [5:0] count;//delay_20ms
reg [2:0] state; //状态标志
reg key_flag; //按键标志位
reg clk_500khz; //500KHZ时钟信号
reg [1:0] col_reg; //寄存扫描列值
reg [1:0] row_reg; //寄存扫描行值
always @(posedge clk or negedge reset)
if(!reset)
begin
clk_500khz<=0;
count<=0;
end
else
begin
if(count>=50)
begin
clk_500khz<=~clk_500khz;
count<=0;
end
else
count<=count+1;
end
always @(posedge clk_500khz or negedge reset)
if(!reset)
begin
row<=2'b00;
state<=0;
end
else
begin
case (state)
0:
begin
row[1:0]<=2'b00;
key_flag<=1'b0;
if(col[1:0]!=2'b11) //有键按下,扫描第一行
begin
state<=1;
row[1:0]<=2'b10;
end
else
state<=0;
end
1:
begin
if(col[1:0]!=2'b11)//判断是否是第一行
begin
state<=5;
end
else //准备扫描第二行
begin
state<=2;
row[1:0]<=2'b01;
end
end
2:
begin
if(col[1:0]!=4'b11) //判断是否是第二行
begin
state<=5;
end
else
begin
state<=0;//重新扫描
row[1:0]<=2'b00;
end
end
5:
begin
if(col[1:0]!=2'b11)
begin
row_reg<=row; //保存扫描列值
col_reg<=col; //保存扫描行值
state<=5;
key_flag<=1'b1; //有键按下
end
else
begin
state<=0;
end
end
endcase
end
always @(clk_500khz or col_reg or row_reg or reset)
if(!reset)
begin
data_1=15;//复位全灭,显示模块只解析0-9,其他全为灭
data_10=15;
data_100=15;
data_1000=15;
end
else
if(key_flag==1'b1)
begin
case ({row_reg,col_reg})
4'b1010:begin data_1=1;data_10=0;data_100=0;data_1000=0;end//key1
4'b1001:begin data_1=2;data_10=0;data_100=0;data_1000=0;end
4'b0110:begin data_1=3;data_10=0;data_100=0;data_1000=0;end
4'b0101:begin data_1=4;data_10=0;data_100=0;data_1000=0;end//key4
default:;//啥也不做
endcase
end
endmodule
module SMDisplay
(
clk,
rst,
dataout,
en,
data_1,
data_10,
data_100,
data_1000
);
input[3:0] data_1,data_10,data_100,data_1000;//个,十,百,千
input clk,rst;
output[7:0] dataout;
output[3:0] en;//COM使能输出
reg[7:0] dataout;//各段数据输出
reg[3:0] en;
reg[15:0] cnt_scan;//扫描频率计数器
reg[3:0] dataout_buf;
always@(posedge clk or negedge rst)
begin
if(!rst)
begin //低电平复位
cnt_scan<=0;
end
else
begin
cnt_scan<=cnt_scan+1;
end
end
always @(cnt_scan)//段码扫描频率
begin
case(cnt_scan[15:14])
2'b00 :
en = 4'b1110;
2'b01 :
en = 4'b1101;
2'b10 :
en = 4'b1011;
2'b11 :
en = 4'b0111;
default :
en = 4'b1110;
endcase
end
always@(en) //对应COM信号给出各段数据,段码
begin
case(en)
4'b1110:
dataout_buf=data_1;//输入将要显示的数字,个位
4'b1101:
dataout_buf=data_10;//十位
4'b1011:
dataout_buf=data_100;//百
4'b0111:
dataout_buf=data_1000;//千
default:;
endcase
end
always@(dataout_buf)
begin
case(dataout_buf) //将要显示的数字译成段码
4'b0000://0
dataout=8'b0000_0011;
4'b0001://1
dataout=8'b1001_1111;
4'b0010://2
dataout=8'b0010_0101;
4'b0011://3
dataout=8'b0000_1101;
4'b0100://4
dataout=8'b1001_1001;
4'b0101://5
dataout=8'b0100_1001;
4'b0110://6
dataout=8'b0100_0001;
4'b0111://7
dataout=8'b0001_1111;
4'b1000://8
dataout=8'b0000_0001;
4'b1001://9
dataout=8'b0000_1001;
default://这里仅编译了0-9这几个数字
dataout=8'b1111_1111;//全灭
endcase
end
endmodule
//矩阵键盘扫描 并将键值送到数码管显示模块和蜂鸣器
module top_matrix_key
(
clk,
rst,
dataout,
en,
row,
col
);
input clk,rst;
input [1:0] col;
output [1:0] row;
output[7:0] dataout;
output[3:0] en;//COM使能输出
wire [3:0] data_1,data_10,data_100,data_1000;
matrix_key u0
(
.clk(clk), //48MHZ
.reset(rst),
.col(col), //列
.row(row), //行
.data_1(data_1),//键值,个位
.data_10(data_10),//十位
.data_100(data_100),//百位
.data_1000(data_1000) //千位
);
SMDisplay u1
(
.clk(clk),
.rst(rst),
.dataout(dataout),
.en(en),
.data_1(data_1),
.data_10(data_10),
.data_100(data_100),
.data_1000(data_1000)
);
bell u2
(
.clk(clk),
.rst(rst),
.data_1(data_1),
);
endmodule
//偶数分频器,外部带入两个参数决定分频系数。默认是2分频
//divdFACTOR--分频系数,实际分频数为divdFACTOR*2
//divdWIDTH--分频计数器的位宽,实际位宽为divdWIDTH+1,该位宽所能表达的最大值>divdFACTOR
module gen_divd(reset,clkin,clkout);
input reset,clkin;
output clkout;
parameter divdWIDTH=1;//分频计数器的位宽,实际位宽为divdWIDTH+1,该位宽所能表达的最大值>divdFACTOR
parameter divdFACTOR=1;//分频系数是divdFACTOR*2
reg clkout;
reg [divdWIDTH:0] cnt;
always @ (negedge reset or posedge clkin)
if(reset==1'b0)
begin
cnt=0;
clkout=0;
end
else
begin
cnt=cnt+1'b1;//常数1要指定位数,否则默认是32位的
if(cnt>=divdFACTOR)
begin
cnt=0;
clkout=~clkout;
end
end
endmodule