
3-8 译码器
//学习3 8译码器的原理,
//拨码开关的 1 2 3作为输入
//本实验采用拨码开关来作为输入,LED作为状态显示
//当然如果你的学习板没有拨码开关,可以用key1 key2 key3 作为数据输入。
module decoder_38(out,key_in);
output[7:0] out; //3 8译码器输出有8钟状态,所以要8个LED灯。
input[2:0] key_in; //(1 2 3)key1 key2 key3 作为数据输入
reg[7:0] out;
always @(key_in)
begin
case(key_in)
3'd0: out=8'b11111110; //LED作为状态显示,低电平有效
3'd1: out=8'b11111101;
3'd2: out=8'b11111011;
3'd3: out=8'b11110111;
3'd4: out=8'b11101111;
3'd5: out=8'b11011111;
3'd6: out=8'b10111111;
3'd7: out=8'b01111111;
endcase
end
endmodule
1位数码管动态显示
//一位数码管试验
//利用分频计数器得到数码管,效果
module SMG_LED (clk_50M,rst,led_bit,dataout);
input clk_50M,rst; //系统时钟50M输入 从12脚输入。
output [7:0] dataout; //我们这里用数码管,
output led_bit; //一位数码管的位选择
reg [7:0] dataout;
reg led_bit;
reg [27:0] count; //分频计数器
//分频计数器
always @ ( posedge clk_50M )
begin
count<=count+1; //计数器自加
end
always @ ( posedge clk_50M or negedge rst)
begin
led_bit <= 'b0; //是数码管的位选择处于导通状态
case ( count[27:24] )
// case ( count[27:24] )这一句希望初学者看明白,
// 也是分频的关键
// 在数码管上面显示0到F
0: dataout<=8'b11000000; //0
1: dataout<=8'b11111001;
2: dataout<=8'b10100100;
3: dataout<=8'b10110000;
4: dataout<=8'b10011001;
5: dataout<=8'b10010010;
6: dataout<=8'b10000010;
7: dataout<=8'b11111000;
8: dataout<=8'b10000000;
9: dataout<=8'b10010000;
10:dataout<=8'b10001000;
11:dataout<=8'b10000011;
12:dataout<=8'b11000110;
13:dataout<=8'b10100001;
14:dataout<=8'b10000110;
15:dataout<=8'b10001110; //f
endcase
end
endmodule
7段数码管静态显示
//本实验就是学习单个数码管的显示
module SMG_LED (clk_50M,led_bit,dataout);
input clk_50M ; //系统时钟50M输入 从12脚输入。
output [7:0] dataout; //我们这里用数码管,
output led_bit; //一位数码管的位选择
reg [7:0] dataout;
reg led_bit;
always @ ( posedge clk_50M )
begin
led_bit <= 'b0; //是数码管的位选择处于导通状态
dataout<=8'b11000000; //修改7段码,可以显示不同的字符
//本实验初始是在数码管显示0
end
数码管静态显示0到7
//7段数码管测试实验:以动态扫描方式在8位数码管
//“同时”显示0--7
//实验的目的是向用户介绍多个数码管动态显示的方法。
//动态显示的方法是,按一定的频率轮流向各个数码管的COM端送出低电平
//,同时送出对应的数据给各段
module led_0_7 (clk,rst,dataout,en);
input clk,rst; //系统时钟50M输入 从12脚输入。
output[7:0] dataout; //数码管的段码输出
output[7:0] en; //数码管的位选使能输出
reg[7:0] dataout;
reg[7:0] en;
reg[15:0] cnt_scan;//扫描频率计数器
reg[4: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:13])
3'b000 :
en = 8'b1111_1110;
3'b001 :
en = 8'b1111_1101;
3'b010 :
en = 8'b1111_1011;
3'b011 :
en = 8'b1111_0111;
3'b100 :
en = 8'b1110_1111;
3'b101 :
en = 8'b1101_1111;
3'b110 :
en = 8'b1011_1111;
3'b111 :
en = 8'b0111_1111;
default :
en = 8'b1111_1110;
endcase
end
always@(en) //对应COM信号给出各段数据
begin
case(en)
8'b1111_1110:
dataout_buf=0;
8'b1111_1101:
dataout_buf=1;
8'b1111_1011:
dataout_buf=2;
8'b1111_0111:
dataout_buf=3;
8'b1110_1111:
dataout_buf=4;
8'b1101_1111:
dataout_buf=5;
8'b1011_1111:
dataout_buf=6;
8'b0111_1111:
dataout_buf=7;
default:
dataout_buf=8;
endcase
end
always@(dataout_buf)
begin
case(dataout_buf)
4'b0000:
dataout=8'b1100_0000;
4'b0001:
dataout=8'b1111_1001;
4'b0010:
dataout=8'b1010_0100;
4'b0011:
dataout=8'b1011_0000;
4'b0100:
dataout=8'b1001_1001;
4'b0101:
dataout=8'b1001_0010;
4'b0110:
dataout=8'b1000_0010;
4'b0111:
dataout=8'b1111_1000;
4'b1000:
dataout=8'b1000_0000;
4'b1001:
dataout=8'b1001_1000;
4'b1010:
dataout=8'b1000_1000;
4'b1011:
dataout=8'b1000_0011;
4'b1100:
dataout=8'b1100_0110;
4'b1101:
dataout=8'b1010_0001;
4'b1110:
dataout=8'b1000_0110;
4'b1111:
dataout=8'b1000_1110;
endcase
end
endmodule
8位优先编码器
//学习编码器的原理
//优先编码器,拨码开关来作为输入,结果由数码管显示
module encode(a,c,en);
input[8:1] a; //由键盘输入数据
output[7:0] c; //结果由数码管显示
reg[7:0] c;
output[7:0] en;
reg[3:0] c_tmp;
integer i;
assign en=0;
always@(a)
begin
c_tmp=0;
for(i=1;i<9;i=i+1) begin
if(a[i])
c_tmp=i;
end
end
always@(c_tmp)
begin
//下面是7段码显示的段码
case(c_tmp)
4'b0000:
c=8'b11000000; //0
4'b0001:
c=8'b11111001; //1
4'b0010:
c=8'b10100100;
4'b0011:
c=8'b10110000;
4'b0100:
c=8'b10011001;
4'b0101:
c=8'b10010010;
4'b0110:
c=8'b10000010;
4'b0111:
c=8'b11111000;
4'b1000:
c=8'b10000000;
4'b1001:
c=8'b10010000;
4'b1010:
c=8'b10001000;
4'b1011:
c=8'b10000011;
4'b1100:
c=8'b11000110;
4'b1101:
c=8'b10100001;
4'b1110:
c=8'b10000110;
4'b1111:
c=8'b10001110; //f
endcase
end
endmodule
buzzer
向蜂鸣器发送一定频率的方波可以使蜂鸣器发出相应的音调,该实验通过设计一个状态机和分频
器使蜂鸣器发出"多来咪发梭拉西多"的音调。
module buzzer(clk,rst,out);
input clk,rst;
output out;
reg out;
reg[3:0] clk_div1; //基频分频计数器,基频为4M
reg[12:0] clk_div2;//音阶分频计数器,由基频分频产生各个音阶
reg[21:0] cnt;//各音阶发声时间长短计数器
reg[2:0] state;
parameter duo=3822, //各个音调的分频系数
lai=3405,
mi=3034,
fa=2865,
suo=2551,
la=2273,
xi=2024,
duo1=1911;
always@(posedge clk or negedge rst)
begin
if(!rst) begin
clk_div1<=0;
end
else begin
if(clk_div1!=9)
clk_div1<=clk_div1+1;
else
clk_div1<=0;
end
end
always@(posedge clk or negedge rst)
begin
if(!rst) begin
clk_div2<=0;
state<=0;
cnt<=0;
out<=0;
end
else if(clk_div1==9) begin
case(state)
3'b000: begin //发“多”
cnt<=cnt+1;
if(cnt==22'h3fffff)
state<=3'b001;
if(clk_div2!=duo)
clk_div2<=clk_div2+1;
else begin
clk_div2<=0;
out<=~out;
end
end
3'b001: begin //发“来”
cnt<=cnt+1;
if(cnt==22'h3fffff)
state<=3'b010;
if(clk_div2!=lai)
clk_div2<=clk_div2+1;
else begin
clk_div2<=0;
out<=~out;
end
end
3'b010:begin //发"米“
cnt<=cnt+1;
if(cnt==22'h3fffff)
state<=3'b011;
if(clk_div2!=mi)
clk_div2<=clk_div2+1;
else begin
clk_div2<=0;
out<=~out;
end
end
3'b011: begin //发"法“
cnt<=cnt+1;
if(cnt==22'h3fffff)
state<=3'b100;
if(clk_div2!=fa)
clk_div2<=clk_div2+1;
else begin
clk_div2<=0;
out<=~out;
end
end
3'b100: begin //发"梭“
cnt<=cnt+1;
if(cnt==22'h3fffff)
state<=3'b101;
if(clk_div2!=suo)
clk_div2<=clk_div2+1;
else begin
clk_div2<=0;
out<=~out;
end
end
3'b101: begin //发"拉“
cnt<=cnt+1;
if(cnt==22'h3fffff)
state<=3'b110;
if(clk_div2!=la)
clk_div2<=clk_div2+1;
else begin
clk_div2<=0;
out<=~out;
end
end
3'b110: begin //发"西“
cnt<=cnt+1;
if(cnt==22'h3fffff)
state<=3'b111;
if(clk_div2!=xi)
clk_div2<=clk_div2+1;
else begin
clk_div2<=0;
out<=~out;
end
end
3'b111: begin //发"多“(高音)
cnt<=cnt+1;
if(cnt==22'h3fffff)
state<=3'b000;
if(clk_div2!=duo1)
clk_div2<=clk_div2+1;
else begin
clk_div2<=0;
out<=~out;
end
end
endcase
end
end
endmodule
LCD1602_B
//www.21eda.com
//本实验是用LCD1602显示英文。(LCD带字库)
module lcd(clk, rs, rw, en,dat);
input clk; //系统时钟输入50M
output [7:0] dat; //LCD的8位数据口
output rs,rw,en; //LCD的控制脚
reg e;
reg [7:0] dat;
reg rs;
reg [15:0] counter;
reg [4:0] current,next;
reg clkr;
reg [1:0] cnt;
parameter set0=4'h0;
parameter set1=4'h1;
parameter set2=4'h2;
parameter set3=4'h3;
parameter dat0=4'h4;
parameter dat1=4'h5;
parameter dat2=4'h6;
parameter dat3=4'h7;
parameter dat4=4'h8;
parameter dat5=4'h9;
parameter dat6=4'hA;
parameter dat7=4'hB;
parameter dat8=4'hC;
parameter dat9=4'hD;
parameter dat10=4'hE;
parameter dat11=5'h10;
parameter nul=4'hF;
always @(posedge clk)
begin
counter=counter+1;
if(counter==16'h000f)
clkr=~clkr;
end
always @(posedge clkr)
begin
current=next;
case(current)
set0: begin rs<=0; dat<=8'h31; next<=set1; end //*设置8位格式,2行,5*7*
set1: begin rs<=0; dat<=8'h0C; next<=set2; end //*整体显示,关光标,不闪烁*/
set2: begin rs<=0; dat<=8'h6; next<=set3; end //*设定输入方式,增量不移位*/
set3: begin rs<=0; dat<=8'h1; next<=dat0; end //*清除显示*/
//上面是LCD的初始化
dat0: begin rs<=1; dat<=8'h3C; next<=dat1; end
dat1: begin rs<=1; dat<="F"; next<=dat2; end
dat2: begin rs<=1; dat<="P"; next<=dat3; end
dat3: begin rs<=1; dat<="G"; next<=dat4; end
dat4: begin rs<=1; dat<="A"; next<=dat5; end
dat5: begin rs<=1; dat<=8'h3E; next<=dat6; end
dat6: begin rs<=1; dat<="G"; next<=dat7; end
dat7: begin rs<=1; dat<="O"; next<=dat8; end
dat8: begin rs<=1; dat<="O"; next<=dat9; end
dat9: begin rs<=1; dat<="D"; next<=dat10; end
dat10: begin rs<=1; dat<="!"; next<=dat11; end
dat11: begin rs<=1; dat<="!"; next<=nul; end
//上面是在这12个状态中要显示的字符 FPGA GOOD!!
nul: begin rs<=0; dat<=8'h00; //行一遍 然后 把液晶的E 脚 拉高
if(cnt!=2'h2)
begin
e<=0;next<=set0;cnt<=cnt+1;
end
else
begin next<=nul; e<=1;
end
end
default: next=set0;
endcase
end
assign en=clkr|e;
assign rw=0;
endmodule
LCD128显示汉字
//利用VHDL驱动LCD128
//视频教程适合我们21EDA电子的所有学习板)
//本实验是用LCD128显示汉字。(LCD带字库)
module LCD128 (clk, rs, rw, en,dat);
input clk; //系统时钟输入50M
output [7:0] dat; //LCD的8位数据口
output rs,rw,en; //LCD的控制脚
reg e;
reg [7:0] dat;
reg rs;
reg [15:0] counter;
reg [6:0] current,next;
reg clkr;
reg [1:0] cnt;
parameter set0=6'h0;
parameter set1=6'h1;
parameter set2=6'h2;
parameter set3=6'h3;
parameter set4=6'h4;
parameter set5=6'h5;
parameter set6=6'h6;
parameter dat0=6'h7;
parameter dat1=6'h8;
parameter dat2=6'h9;
parameter dat3=6'hA;
parameter dat4=6'hB;
parameter dat5=6'hC;
parameter dat6=6'hD;
parameter dat7=6'hE;
parameter dat8=6'hF;
parameter dat9=6'h10;
parameter dat10=6'h12;
parameter dat11=6'h13;
parameter dat12=6'h14;
parameter dat13=6'h15;
parameter dat14=6'h16;
parameter dat15=6'h17;
parameter dat16=6'h18;
parameter dat17=6'h19;
parameter dat18=6'h1A;
parameter dat19=6'h1B;
parameter dat20=6'h1C;
parameter dat21=6'h1D;
parameter dat22=6'h1E;
parameter dat23=6'h1F;
parameter dat24=6'h20;
parameter dat25=6'h21;
parameter dat26=6'h22;
parameter dat27=6'h23;
parameter dat28=6'h24;
parameter dat29=6'h25;
parameter dat30=6'h26;
parameter dat31=6'h27;
parameter dat32=6'h28;
parameter dat33=6'h29;
parameter dat34=6'h2A;
parameter dat35=6'h2B;
parameter dat36=6'h2C;
parameter dat37=6'h2E;
parameter dat38=6'h2F;
parameter dat39=6'h30;
parameter dat40=6'h31;
parameter dat41=6'h32;
parameter dat42=6'h33;
parameter dat43=6'h34;
parameter nul=6'h35;
always @(posedge clk) //da de shi zhong pinlv
begin
counter=counter+1;
if(counter==16'h000f)
clkr=~clkr;
end
always @(posedge clkr)
begin
current=next;
case(current)
set0: begin rs<=0; dat<=8'h31; next<=set1; end //*设置8位格式,2行,5*7*
set1: begin rs<=0; dat<=8'h0C; next<=set2; end //*整体显示,关光标,不闪烁*/
set2: begin rs<=0; dat<=8'h6; next<=set3; end //*设定输入方式,增量不移位*/
set3: begin rs<=0; dat<=8'h1; next<=dat0; end //*清除显示*/
dat0: begin rs<=1; dat<=8'hc9; next<=dat1; end //显示第一行
dat1: begin rs<=1; dat<=8'hee; next<=dat2; end
dat2: begin rs<=1; dat<=8'hdb; next<=dat3; end
dat3: begin rs<=1; dat<=8'hda;next<=dat4; end
dat4: begin rs<=1; dat<=8'hca; next<=dat5; end
dat5: begin rs<=1; dat<=8'hd0; next<=dat6; end
dat6: begin rs<=1; dat<="2"; next<=dat7; end
dat7: begin rs<=1; dat<="1";next<=dat8; end
dat8: begin rs<=1; dat<="E"; next<=dat9; end
dat9: begin rs<=1; dat<="D";next<= dat10 ; end
dat10: begin rs<=1; dat<=8'hB5; next<=dat11; end
dat11: begin rs<=1; dat<=8'hE7; next<=dat12; end
dat12: begin rs<=1; dat<=8'hd7;next<=dat13; end
dat13: begin rs<=1; dat<=8'hd3; next<=set4; end
set4: begin rs<=0; dat<=8'h90; next<=dat14; end //显示第二行
dat14: begin rs<=1; dat<="C"; next<=dat15; end
dat15: begin rs<=1; dat<="P"; next<=dat16; end
dat16: begin rs<=1; dat<="L"; next<=dat17; end
dat17: begin rs<=1; dat<="D"; next<=dat18; end
dat18: begin rs<=1; dat<="-"; next<=dat19; end
dat19: begin rs<=1; dat<="2"; next<=dat20; end
dat20: begin rs<=1; dat<="1"; next<=dat21; end
dat21: begin rs<=1; dat<="E"; next<=dat22; end
dat22: begin rs<=1; dat<="D"; next<=dat23; end
dat23: begin rs<=1; dat<="A"; next<=dat24 ; end
dat24: begin rs<=1; dat<=8'hbf; next<=dat25; end
dat25: begin rs<=1; dat<=8'haa; next<=dat26; end
dat26: begin rs<=1; dat<=8'hb7; next<=dat27; end
dat27: begin rs<=1; dat<=8'ha2; next<=dat28; end
dat28: begin rs<=1; dat<=8'hb0; next<=dat29; end
dat29: begin rs<=1; dat<=8'he5; next<=set5 ; end
set5: begin rs<=0; dat<=8'h88; next<=dat30; end //显示第三行
dat30: begin rs<=1; dat<="L"; next<=dat31; end
dat31: begin rs<=1; dat<="C"; next<=dat32; end
dat32: begin rs<=1; dat<="D"; next<=dat33; end
dat33: begin rs<=1; dat<="-"; next<=dat34; end
dat34: begin rs<=1; dat<=8'hbf; next<=dat35; end
dat35: begin rs<=1; dat<=8'hd8; next<=dat36; end
dat36: begin rs<=1; dat<=8'hd6; next<=dat37; end
dat37: begin rs<=1; dat<=8'hc6; next<=set6; end
set6: begin rs<=0; dat<=8'h9C; next<=dat38; end //显示第四行
dat38: begin rs<=1; dat<="G"; next<=dat39; end
dat39: begin rs<=1; dat<="O"; next<=dat40; end
dat40: begin rs<=1; dat<="O"; next<=dat41; end
dat41: begin rs<=1; dat<="D"; next<=dat42; end
dat42: begin rs<=1; dat<="!"; next<=dat43; end
dat43: begin rs<=1; dat<="!"; next<=nul; end
nul: begin rs<=0; dat<=8'h00; // 把液晶的E 脚 拉高
if(cnt!=2'h2)
begin
e<=0;next<=set0;cnt<=cnt+1;
end
else
begin next<=nul; e<=1;
end
end
default: next=set0;
endcase
end
assign en=clkr|e;
assign rw=0;
endmodule
LED花样流水灯
//LED流水灯试验
//利用分频计数器得到显示流水灯的效果
module ledwater (clk_50M,rst,dataout);
input clk_50M,rst; //系统时钟50M输入 从12脚输入。
output [11:0] dataout; //我们这里用12个LED灯,
reg [11:0] dataout;
reg [27:0] count; //分频计数器
//分频计数器
always @ ( posedge clk_50M )
begin
count<=count+1;
end
always @ ( posedge clk_50M or negedge rst)
begin
case ( count[27:24] )
// case ( count[25:22] )这一句希望初学者看明白,
// 也是分频的关键
// 只有在0的那一位 对应的LED灯才亮。
0: dataout<=12'b111000111000;
1: dataout<=12'b000111000111;
2: dataout<=12'b110110110110;
3: dataout<=12'b101101101101;
4: dataout<=12'b011011011011;
5: dataout<=12'b000000000000;
6: dataout<=12'b010000010000;
7: dataout<=12'b111000111000;
8: dataout<=12'b111101111101;
9: dataout<=12'b111111111111;
10: dataout<=12'b111101111101;
11:dataout<=12'b111000111000;
12:dataout<=12'b010000010000;
13:dataout<=12'b000000000000;
14:dataout<=12'b111110000011;
15:dataout<=12'b000011111110;
endcase
end
endmodule
PWM+LED
//学习PWM原理,
//拨码开关的 1 2 3 4 5 6 7 8作为输入
//本实验采用拨码开关来控制LED灯的亮暗
//当然如果你的学习板没有拨码开关,可以用key1 key2 key3 key4 作为输入。
//视频教程适合我们21EDA电子的所有学习板
module pwm(
switch,
clk,
led0
);
input clk; //系统时钟输入50M
input [7:0]switch; //拨码开关的 1 2 3 4 5 6 7 8作为输入
output led0; //LED灯输出显示亮暗强度
reg led0;
reg [7:0]counter;
always @(posedge clk)
begin
counter=counter+1;
if(counter>=switch)
led0=0;
else
led0=1;
end
endmodule
按键与数码管显示
//学习按键识别,FPGA检测
//key1 key2 key3 key4的状态作为数据输入,数码管作为状态显示
//视频教程适合我们21EDA电子的所有学习板
module key_led(clk_50M,key,duan_ma,wei_ma);
input clk_50M; //系统时钟50M输入 从12脚输入。
input [3:0] key; //key1 key2 key3 key4为输入的键码的值
output [3:0] wei_ma; //数码管的位选
output [7:0] duan_ma; //数码管的段码ABCDEFGH
wire [3:0] key;
reg [7:0] duan_ma;
reg [3:0] wei_ma;
reg [3:0] key_temp; //设置了一个寄存器
always @ (posedge clk_50M )
begin
key_temp<=key; //把键码的值赋给寄存器
case ( key_temp )
4'b1110:duan_ma<=8'b1111_1001; //段码//KEY1按下去显示1
4'b1101:duan_ma<=8'b1010_0100; //段码//KEY2按下去显示2
4'b1011:duan_ma<=8'b1011_0000; //段码//KEY3按下去显示3
4'b0111:duan_ma<=8'b1001_1001; //段码//KEY4按下去显示4
endcase
end
always @ ( posedge clk_50M )
begin
case( key_temp )
4'b0111:wei_ma<=4'b0111; //位选信号
4'b1011:wei_ma<=4'b1011;
4'b1101:wei_ma<=4'b1101;
4'b1110:wei_ma<=4'b1110;
endcase
end
endmodule
拨码开关_LED
//拨码开关的 1 2 3 4 5 6 7 8作为输入
//本实验采用拨码开关来控制LED灯
//当然如果你的学习板没有拨码开关,可以用key1 key2 key3 key4 作为输入。
//视频教程适合我们21EDA电子的所有学习板
module led(
switch,
led
); // 模块名led
input [7:0] switch; //拨码开关
output [7:0] led; //LED灯输出显示
assign led =switch; //把拨码开关的数据在LED灯上面显示
endmodule
还没弄懂
除法器
//两个3位二进制数的除法,结果(整数商)输出到数码管显示
module div(a,b,c,en);
input[2:0] a,b;//a 被除数,b 除数
output[7:0] c;
reg[7:0] c;
output[7:0] en;
reg[3:0] c_tmp;//商(整数部分)
reg[2:0] temp_reg;//计算的中间结果寄存器
integer i;
assign en=0;
always@(a or b or temp_reg)
begin
temp_reg=0;
c_tmp=0;
if(b==0)
c_tmp=4'he;
else begin
if(a[2]>=b) begin
c_tmp[2]=1;
temp_reg[2]=a[2]-b;
end
else begin
c_tmp[2]=0;
temp_reg[2]=a[2];
end
if({temp_reg[2],a[1]}>=b) begin
c_tmp[1]=1;
temp_reg[2:1]={temp_reg[2],a[1]}-b;
end
else begin
c_tmp[1]=0;
temp_reg[2:1]={temp_reg[2],a[1]};
end
if({temp_reg[2:1],a[0]}>=b) begin
c_tmp[0]=1;
temp_reg=0;
end
else begin
c_tmp[0]=0;
temp_reg=0;
end
end
end
always@(c_tmp)
begin
case(c_tmp)
4'b0000:
c=8'b11000000;
4'b0001:
c=8'b11111001;
4'b0010:
c=8'b10100100;
4'b0011:
c=8'b10110000;
4'b0100:
c=8'b10011001;
4'b0101:
c=8'b10010010;
4'b0110:
c=8'b10000010;
4'b0111:
c=8'b11111000;
4'b1000:
c=8'b10000000;
4'b1001:
c=8'b10010000;
4'b1010:
c=8'b10001000;
4'b1011:
c=8'b10000011;
4'b1100:
c=8'b11000110;
4'b1101:
c=8'b10100001;
4'b1110:
c=8'b10000110;
4'b1111:
c=8'b10001110;
endcase
end
endmodule
串口与电脑通信
//本模块的功能是验证实现和PC机进行基本的串口通信的功能。需要在
//PC机上安装一个串口调试工具来验证程序的功能。
//程序实现了一个收发一帧10个bit(即无奇偶校验位)的串口控
//制器,10个bit是1位起始位,8个数据位,1个结束
//位。串口的波特律由程序中定义的div_par参数决定,更改该参数可以实
//现相应的波特率。程序当前设定的div_par 的值是0x145,对应的波特率是
//9600。用一个8倍波特率的时钟将发送或接受每一位bit的周期时间
//划分为8个时隙以使通信同步.
//程序的工作过程是:串口处于全双工工作状态,按动key1,FPGA向PC发送“21 EDA"
//字符串(串口调试工具设成按ASCII码接受方式);PC可随时向FPGA发送0-F的十六进制
//数据,FPGA接受后显示在7段数码管上。
//视频教程适合我们21EDA电子的所有学习板
module serial(clk,rst,rxd,txd,en,seg_data,key_input,lowbit);
input clk,rst;
input rxd;//串行数据接收端
input key_input;//按键输入
output[7:0] en;
output[7:0] seg_data;
reg[7:0] seg_data;
output txd;//串行数据发送端
output lowbit;
// 没弄明白
////////////////////inner reg////////////////////
reg[15:0] div_reg;//分频计数器,分频值由波特率决定。分频后得到频率8倍波特率的时钟
reg[2:0] div8_tras_reg;//该寄存器的计数值对应发送时当前位于的时隙数
reg[2:0] div8_rec_reg;//该寄存器的计数值对应接收时当前位于的时隙数
reg[3:0] state_tras;//发送状态寄存器
reg[3:0] state_rec;//接受状态寄存器
reg clkbaud_tras;//以波特率为频率的发送使能信号
reg clkbaud_rec;//以波特率为频率的接受使能信号
reg clkbaud8x;//以8倍波特率为频率的时钟,它的作用是将发送或接受一个bit的时钟周期分为8个时隙
reg recstart;//开始发送标志
reg recstart_tmp;
reg trasstart;//开始接受标志
reg rxd_reg1;//接收寄存器1
reg rxd_reg2;//接收寄存器2,因为接收数据为异步信号,故用两级缓存
reg txd_reg;//发送寄存器
reg[7:0] rxd_buf;//接受数据缓存
reg[7:0] txd_buf;//发送数据缓存
reg[2:0] send_state;//每次按键给PC发送"Welcome"字符串,这是发送状态寄存器
reg[19:0] cnt_delay;//延时去抖计数器
reg start_delaycnt;//开始延时计数标志
reg key_entry1,key_entry2;//确定有键按下标志
////////////////////////////////////////////////
parameter div_par=16'h145;//分频参数,其值由对应的波特率计算而得,按此参数分频的时钟频率是波倍特率的8
//倍,此处值对应9600的波特率,即分频出的时钟频率是9600*8 (CLK 50M)
////////////////////////////////////////////////
assign txd=txd_reg;
assign lowbit=0;
assign en=0;//7段数码管使能信号赋值
always@(posedge clk )
begin
if(!rst) begin
cnt_delay<=0;
start_delaycnt<=0;
end
else if(start_delaycnt) begin
if(cnt_delay!=20'd800000) begin
cnt_delay<=cnt_delay+1;
end
else begin
cnt_delay<=0;
start_delaycnt<=0;
end
end
else begin
if(!key_input&&cnt_delay==0)
start_delaycnt<=1;
end
end
always@(posedge clk)
begin
if(!rst)
key_entry1<=0;
else begin
if(key_entry2)
key_entry1<=0;
else if(cnt_delay==20'd800000) begin
if(!key_input)
key_entry1<=1;
end
end
end
always@(posedge clk )
begin
if(!rst)
div_reg<=0;
else begin
if(div_reg==div_par-1)
div_reg<=0;
else
div_reg<=div_reg+1;
end
end
always@(posedge clk)//分频得到8倍波特率的时钟
begin
if(!rst)
clkbaud8x<=0;
else if(div_reg==div_par-1)
clkbaud8x<=~clkbaud8x;
end
always@(posedge clkbaud8x or negedge rst)
begin
if(!rst)
div8_rec_reg<=0;
else if(recstart)//接收开始标志
div8_rec_reg<=div8_rec_reg+1;//接收开始后,时隙数在8倍波特率的时钟下加1循环
end
always@(posedge clkbaud8x or negedge rst)
begin
if(!rst)
div8_tras_reg<=0;
else if(trasstart)
div8_tras_reg<=div8_tras_reg+1;//发送开始后,时隙数在8倍波特率的时钟下加1循环
end
always@(div8_rec_reg)
begin
if(div8_rec_reg==7)
clkbaud_rec=1;//在第7个时隙,接收使能信号有效,将数据打入
else
clkbaud_rec=0;
end
always@(div8_tras_reg)
begin
if(div8_tras_reg==7)
clkbaud_tras=1;//在第7个时隙,发送使能信号有效,将数据发出
else
clkbaud_tras=0;
end
always@(posedge clkbaud8x or negedge rst)
begin
if(!rst) begin
txd_reg<=1;
trasstart<=0;
txd_buf<=0;
state_tras<=0;
send_state<=0;
key_entry2<=0;
end
else begin
if(!key_entry2) begin
if(key_entry1) begin
key_entry2<=1;
txd_buf<=8'd50; //"2"
end
end
else begin
case(state_tras)
4'b0000: begin //发送起始位
if(!trasstart&&send_state<7)
trasstart<=1;
else if(send_state<7) begin
if(clkbaud_tras) begin
txd_reg<=0;
state_tras<=state_tras+1;
end
end
else begin
key_entry2<=0;
state_tras<=0;
end
end
4'b0001: begin //发送第1位
if(clkbaud_tras) begin
txd_reg<=txd_buf[0];
txd_buf[6:0]<=txd_buf[7:1];
state_tras<=state_tras+1;
end
end
4'b0010: begin //发送第2位
if(clkbaud_tras) begin
txd_reg<=txd_buf[0];
txd_buf[6:0]<=txd_buf[7:1];
state_tras<=state_tras+1;
end
end
4'b0011: begin //发送第3位
if(clkbaud_tras) begin
txd_reg<=txd_buf[0];
txd_buf[6:0]<=txd_buf[7:1];
state_tras<=state_tras+1;
end
end
4'b0100: begin //发送第4位
if(clkbaud_tras) begin
txd_reg<=txd_buf[0];
txd_buf[6:0]<=txd_buf[7:1];
state_tras<=state_tras+1;
end
end
4'b0101: begin //发送第5位
if(clkbaud_tras) begin
txd_reg<=txd_buf[0];
txd_buf[6:0]<=txd_buf[7:1];
state_tras<=state_tras+1;
end
end
4'b0110: begin //发送第6位
if(clkbaud_tras) begin
txd_reg<=txd_buf[0];
txd_buf[6:0]<=txd_buf[7:1];
state_tras<=state_tras+1;
end
end
4'b0111: begin //发送第7位
if(clkbaud_tras) begin
txd_reg<=txd_buf[0];
txd_buf[6:0]<=txd_buf[7:1];
state_tras<=state_tras+1;
end
end
4'b1000: begin //发送第8位
if(clkbaud_tras) begin
txd_reg<=txd_buf[0];
txd_buf[6:0]<=txd_buf[7:1];
state_tras<=state_tras+1;
end
end
4'b1001: begin //发送停止位
if(clkbaud_tras) begin
txd_reg<=1;
txd_buf<=8'h55;
state_tras<=state_tras+1;
end
end
4'b1111:begin
if(clkbaud_tras) begin
state_tras<=state_tras+1;
send_state<=send_state+1;
trasstart<=0;
case(send_state)
3'b000:
txd_buf<=8'd49;//"1"
3'b001:
txd_buf<=8'd32;//" "
3'b010:
txd_buf<=8'd69;//"E"
3'b011:
txd_buf<=8'd68;//"D"
3'b100:
txd_buf<=8'd65;//"A"
3'b101:
txd_buf<=8'd10;//"e"
default:
txd_buf<=0;
endcase
end
end
default: begin
if(clkbaud_tras) begin
state_tras<=state_tras+1;
trasstart<=1;
end
end
endcase
end
end
end
always@(posedge clkbaud8x or negedge rst)//接受PC机的数据
begin
if(!rst) begin
rxd_reg1<=0;
rxd_reg2<=0;
rxd_buf<=0;
state_rec<=0;
recstart<=0;
recstart_tmp<=0;
end
else begin
rxd_reg1<=rxd;
rxd_reg2<=rxd_reg1;
if(state_rec==0) begin
if(recstart_tmp==1) begin
recstart<=1;
recstart_tmp<=0;
state_rec<=state_rec+1;
end
else if(!rxd_reg1&&rxd_reg2) //检测到起始位的下降沿,进入接受状态
recstart_tmp<=1;
end
else if(state_rec>=1&&state_rec<=8) begin
if(clkbaud_rec) begin
rxd_buf[7]<=rxd_reg2;
rxd_buf[6:0]<=rxd_buf[7:1];
state_rec<=state_rec+1;
end
end
else if(state_rec==9) begin
if(clkbaud_rec) begin
state_rec<=0;
recstart<=0;
end
end
end
end
always@(rxd_buf) //将接受的数据用数码管显示出来
begin
case (rxd_buf)
8'h30:
seg_data=8'b11000000;
8'h31:
seg_data=8'b11111001;
8'h32:
seg_data=8'b10100100;
8'h33:
seg_data=8'b10110000;
8'h34:
seg_data=8'b10011001;
8'h35:
seg_data=8'b10010010;
8'h36:
seg_data=8'b10000010;
8'h37:
seg_data=8'b11111000;
8'h38:
seg_data=8'b10000000;
8'h39:
seg_data=8'b10010000;
8'h41:
seg_data=8'b10001000;//a
8'h42:
seg_data=8'b10000011;
8'h43:
seg_data=8'b11000110;
8'h44:
seg_data=8'b10100001;
8'h45:
seg_data=8'b10000110;
8'h46:
seg_data=8'b10001110;
default:
seg_data=8'b11111111;
endcase
end
endmodule
点阵显示爱心形
//本实验学习点阵模块的使用
//其实原理和使用动态数码管的原理一样的
//在点阵上面显示一个爱心
//视频教程适合我们21EDA电子的所有学习板
module led_0_7 (clk,rst,dataout,en);
input clk,rst; //系统时钟50M输入 从12脚输入。
output[7:0] dataout; //数码管的段码输出
output[7:0] en; //数码管的位选使能输出
reg[7:0] dataout;
reg[7:0] en;
reg[15:0] cnt_scan;//扫描频率计数器
reg[4: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:13])
3'b000 :
en = 8'b1111_1110;
3'b001 :
en = 8'b1111_1101;
3'b010 :
en = 8'b1111_1011;
3'b011 :
en = 8'b1111_0111;
3'b100 :
en = 8'b1110_1111;
3'b101 :
en = 8'b1101_1111;
3'b110 :
en = 8'b1011_1111;
3'b111 :
en = 8'b0111_1111;
default :
en = 8'b1111_1110;
endcase
end
always@(en) //对应COM信号给出各段数据
begin
case(en)
8'b1111_1110:
dataout_buf=0;
8'b1111_1101:
dataout_buf=1;
8'b1111_1011:
dataout_buf=2;
8'b1111_0111:
dataout_buf=3;
8'b1110_1111:
dataout_buf=4;
8'b1101_1111:
dataout_buf=5;
8'b1011_1111:
dataout_buf=6;
8'b0111_1111:
dataout_buf=7;
default:
dataout_buf=8;
endcase
end
always@(dataout_buf)
begin
//在点阵上面显示一个爱心需要的点阵代码
case(dataout_buf)
4'b0000:
dataout=8'b11111111;
4'b0001:
dataout=8'b11111111;
4'b0010:
dataout=8'b10011001;
4'b0011:
dataout=8'b01100110;
4'b0100:
dataout=8'b01111110;
4'b0101:
dataout=8'b10111101;
4'b0110:
dataout=8'b11011011;
4'b0111:
dataout=8'b11100111;
endcase
end
endmodule
多路选择器
//学习多路选择器的原理,
//拨码开关的 4 作为A的输入
//多路选择器,a为1则选择b,为0则选择c,
//拨码开关的 1 2 3 作为B的输入
//拨码开关的 6 7 8 作为C的输入
//结果输出到数码管显示
//当然如果你的学习板没有拨码开关,可以用key1 key2 key3 key4 作为输入。
//视频教程适合我们21EDA电子的所有学习板
module mux(a,b,c,d,en);
input a; //拨码开关的 4 作为A的输入
//多路选择器,a为1则选择b,为0则选择c
input[2:0]b; //拨码开关的 1 2 3 作为B的输入
input[2:0]c; //拨码开关的 6 7 8 作为C的输入
output[7:0] d; //7段码显示的段码
reg[7:0] d;
output en;
wire[3:0] d_tmp;
assign en=0;
assign d_tmp=a? b:c;
always@(d_tmp)
begin
//下面是7段码显示的段码
case(d_tmp)
4'b0000:
d=8'b11000000;
4'b0001:
d=8'b11111001;
4'b0010:
d=8'b10100100;
4'b0011:
d=8'b10110000;
4'b0100:
d=8'b10011001;
4'b0101:
d=8'b10010010;
4'b0110:
d=8'b10000010;
4'b0111:
d=8'b11111000;
4'b1000:
d=8'b10000000;
4'b1001:
d=8'b10010000;
4'b1010:
d=8'b10001000;
4'b1011:
d=8'b10000011;
4'b1100:
d=8'b11000110;
4'b1101:
d=8'b10100001;
4'b1110:
d=8'b10000110;
4'b1111:
d=8'b10001110;
endcase
end
endmodule
// 没弄明白
二进制转BCD码
4位二进制数转BCD码,由键盘输入,结果由数码管显示
module bcd (clk,a,c,en )
input clk;
input [3:0] a ;
output[7:0] c ;
reg [7:0] c ;
output[1:0] en ;
reg[1:0] en;
reg[7:0] code_data;
reg[3:0] c_tmp;
reg[19:0] cnt;
always@(posedge clk )
begin
if(cnt!=20'h5ffff)
cnt<=cnt+1;
else
cnt<=0;
end
always@(posedge clk )
begin
if(cnt==20'h5ffff)
en<=~en;
end
always@(en)
begin
case(en)
2'b01:
c_tmp=code_data[3:0];
2'b10:
c_tmp=code_data[7:4];
default:
c_tmp=0;
endcase
end
always @(a) //转化过程
begin
case (a[3:0])
3'b0000 : code_data [7:1] = 7'b0000000;
3'b0001 : code_data [7:1] = 7'b0000001;
3'b0010 : code_data [7:1] = 7'b0000010;
3'b0011 : code_data [7:1] = 7'b0000011;
3'b0100 : code_data [7:1] = 7'b0000100;
3'b0101 : code_data [7:1] = 7'b0001000;
3'b0110 : code_data [7:1] = 7'b0001001;
3'b0111 : code_data [7:1] = 7'b0001010;
default : code_data [7:1] = 7'b0000000;
endcase
code_data[0] = a[0];
end
always@(c_tmp)
begin
case(c_tmp)
4'b0000:
c=8'b1100_0000;
4'b0001:
c=8'b1111_1001;
4'b0010:
c=8'b1010_0100;
4'b0011:
c=8'b1011_0000;
4'b0100:
c=8'b1001_1001;
4'b0101:
c=8'b1001_0010;
4'b0110:
c=8'b1000_0010;
4'b0111:
c=8'b1111_1000;
4'b1000:
c=8'b1000_0000;
4'b1001:
c=8'b1001_1000;
4'b1010:
c=8'b1000_1000;
4'b1011:
c=8'b1000_0011;
4'b1100:
c=8'b1100_0110;
4'b1101:
c=8'b1010_0001;
4'b1110:
c=8'b1000_0110;
4'b1111:
c=8'b1000_1110;
endcase
end
endmodule
分频1秒和0.5秒
//利用计数器分频
//利用分频计数器得到显示一秒和0.5的闪烁效果
//视频教程适合我们21EDA电子的所有学习板
module ledwater (clk_50M,led_out,f_led_out);
input clk_50M; //系统时钟输入50M
output led_out;
output f_led_out;
reg [24:0] count; //分频计数器,25000000分频 一秒
reg [24:0] f_count;//分频计数器,12500000分频 0.5秒
reg div_clk, f_div_clk;
reg led_out, f_led_out;
//分频计数器。得到一秒的频率
always @ ( posedge clk_50M )
begin
if ( count==25000000 )
begin
div_clk<=~div_clk;
count<=0;
end
else
count<=count+1;
led_out<=~div_clk;
end
//分频计数器。得到0.5秒的频率
always @ ( posedge clk_50M )
begin
if ( f_count==12500000 )
begin
f_div_clk<=~f_div_clk;
f_count<=0;
end
else
f_count<=f_count+1;
f_led_out<=~f_div_clk;
end
endmodule
简单状态机控制步进电机
//简单的状态机,利用状态机控制步进电机
//state0--state1--state2--state3--state4--state5--state6-state7--state0
//视频教程适合我们21EDA电子的所有学习板
module state_machine(clk,rst,c);
input clk,rst; //系统时钟50M输入 从12脚输入。
output [3:0] c; //输出控制步进电机
reg [3:0] c;
parameter state0=3'b000,
state1=3'b001,
state2=3'b010,
state3=3'b011,
state4=3'b100,
state5=3'b101,
state6=3'b110,
state7=3'b111;
reg[2:0] state;
reg[23:0] cnt;
always@(posedge clk or negedge rst)
begin
if(!rst) begin
state<=state0;
cnt<=0;
end
else begin
cnt<=cnt+1;
if(cnt==24'hffffff) begin
case(state)
state0:
state<=state1;
state1:
state<=state2;
state2:
state<=state3;
state3:
state<=state4;
state4:
state<=state5;
state5:
state<=state6;
state6:
state<=state7;
state7:
state<=state0;
endcase
end
end
end
always@(state)
begin
case(state)
state0:
c=8'b0001;
state1:
c=8'b0100;
state2:
c=8'b0010;
state3:
c=8'b1000;
state4:
c=8'b0001;
state5:
c=8'b0100;
state6:
c=8'b0010;
state7:
c=8'b1000;
endcase
end
endmodule
矩阵键盘
矩阵键盘实验1:向用户介绍矩阵键盘扫描实现的方法,没有考虑去抖和判断键弹起的问题;把相应的键值显示在数码管上
module key1(clk,rst,row,column,dataout,en)
input clk,rst;
input[3:0] column;//列线
output[3:0] row;//行线
output[7:0] dataout;//数码管显示数据
reg[7:0] dataout;
output[7:0] en;//数码管显示使能
reg[3:0] row;
reg[3:0] scan_key; //扫描码寄存器
reg[15:0] cnt_scan;//扫描频率计数器
assign en=0;
always@(posedge clk or negedge rst)
begin
if(!rst) begin
row<=4'b1110;
cnt_scan<=0;
end
else begin
cnt_scan<=cnt_scan+1;
if(cnt_scan==16'hffff) begin
row[3:1]<=row[2:0];//没弄明白
row[0]<=row[3]; //4根行线循环送出低电平
end
end
end
always@(posedge clk or negedge rst)
begin
if(!rst) begin
scan_key<=0;
end
else begin
case(row) //该case结果检测何处有键按下
4'b1110:
case(column)
4'b1110: begin
scan_key<=0;
end
4'b1101: begin
scan_key<=1;
end
4'b1011: begin
scan_key<=2;
end
4'b0111: begin
scan_key<=3;
end
endcase
4'b1101:
case(column)
4'b1110: begin
scan_key<=4;
end
4'b1101: begin
scan_key<=5;
end
4'b1011: begin
scan_key<=6;
end
4'b0111: begin
scan_key<=7;
end
endcase
4'b1011:
case(column)
4'b1110: begin
scan_key<=8;
end
4'b1101: begin
scan_key<=9;
end
4'b1011: begin
scan_key<=10;
end
4'b0111: begin
scan_key<=11;
end
endcase
4'b0111:
case(column)
4'b1110: begin
scan_key<=12;
end
4'b1101: begin
scan_key<=13;
end
4'b1011: begin
scan_key<=14;
end
4'b0111: begin
scan_key<=15;
end
endcase
default:
scan_key<=15;
endcase
end
end
always@(scan_key)
begin
case(scan_key)
4'b0000:
dataout<=8'b11000000;
4'b0001:
dataout<=8'b11111001;
4'b0010:
dataout<=8'b10100100;
4'b0011:
dataout<=8'b10110000;
4'b0100:
dataout<=8'b10011001;
4'b0101:
dataout<=8'b10010010;
4'b0110:
dataout<=8'b10000010;
4'b0111:
dataout<=8'b11111000;
4'b1000:
dataout<=8'b10000000;
4'b1001:
dataout<=8'b10010000;
4'b1010:
dataout<=8'b10001000;
4'b1011:
dataout<=8'b10000011;
4'b1100:
dataout<=8'b11000110;
4'b1101:
dataout<=8'b10100001;
4'b1110:
dataout<=8'b10000110;
4'b1111:
dataout<=8'b10001110;
endcase
end
endmodule
秒表 数码管显示
//程序的思想和我们用的51单片机的思想一样
//视频教程适合我们21EDA电子的所有学习板
module watch(clk,out_wei,out_duan,rst,key2); //key2==27pin
input rst;
input clk;
input key2;
output [5:0]out_wei;
output [7:0]out_duan;
reg [5:0]out_wei=6'b000000;
reg [7:0]out_duan=8'b00000011; //a b c d e f g dp
reg [4:0]count;
reg [3:0]count1;
reg [14:0]count2;
reg [7:0]sec_l=8'b00000011; //zero at first
reg [7:0]sec_h=8'b00000011;
reg [7:0]fen_l=8'b00000011;
reg [7:0]fen_h=8'b00000011;
reg [7:0]msec_l=8'b00000011;
reg [7:0]msec_h=8'b00000011;
reg [3:0]s_1=0;
reg [3:0]s_2=0;
reg [3:0]s_3=0;
reg [3:0]s_4=0;
reg [3:0]s_5=0;
reg [3:0]s_6=0;
reg clk_out;
reg pause;//信号
always@(posedge clk) begin //fenpin
if(count2==25000) begin //one of thousand secend 25000
count2<=0;
clk_out<=~clk_out;
end
else count2<=count2+1;
end
always@(posedge clk_out) begin //scan
count<=count+1'b1;
case(count)
1 :begin
out_wei<=6'b111110;
out_duan<=msec_l;
end
3:begin
out_wei<=6'b111101;
out_duan<=msec_h;
end
6:begin
out_wei<=6'b111011;
out_duan<=sec_l;
end
9:begin
out_wei<=6'b110111;
out_duan<=sec_h;
end
12:begin
out_wei<=6'b101111;
out_duan<=fen_l;
end
15:begin
out_wei<=6'b011111;
out_duan<=fen_h;
end
18:count<=0;
endcase
end
always@(negedge key2) begin
pause<=~pause;
end
always@(posedge clk_out or negedge rst) begin //minite secend
if(!rst) begin
s_1<=0;
s_2<=0;
s_3<=0;
s_4<=0;
s_5<=0;
s_6<=0;
end
else if(count1==10)begin //if 1s l+1
count1<=0;
if(s_6==9) begin
s_6<=0;
if(s_5==9) begin
s_5<=0;
if(s_1==9) begin
s_1<=0;
if(s_2==5) begin
s_2<=0;
if(s_3==9) begin
s_3<=0;
if(s_4==5)
s_4<=0;
else s_4<=s_4+1;
end else s_3<=s_3+1;
end else s_2<=s_2+1;
end else s_1<=s_1+1;
end else s_5<=s_5+1;
end else s_6<=s_6+1;
end
else if(pause==1) begin
count1<=count1+1;
end
end
//这下面全部是扫描显示用的。
always@(s_1 or s_2 or s_3 or s_4 or s_5 or s_6) begin
case(s_1)
0:sec_l=8'b11000000;
1:sec_l=8'b11111001;
2:sec_l=8'b10100100;
3:sec_l=8'b10110000;
4:sec_l=8'b10011001;
5:sec_l=8'b10010010;
6:sec_l=8'b10000010;
7:sec_l=8'b11111000;
8:sec_l=8'b10000000;
9:sec_l=8'b10010000;
default:sec_l=1'bx;
endcase
case(s_2)
0:sec_h=8'b11000000;
1:sec_h=8'b11111001;
2:sec_h=8'b10100100;
3:sec_h=8'b10110000;
4:sec_h=8'b10011001;
5:sec_h=8'b10010010;
6:sec_h=8'b10000010;
default:sec_h=1'bx;
endcase
case(s_3)
0:fen_l=8'b11000000;
1:fen_l=8'b11111001;
2:fen_l=8'b10100100;
3:fen_l=8'b10110000;
4:fen_l=8'b10011001;
5:fen_l=8'b01001001;
6:fen_l=8'b10010010;
7:fen_l=8'b10000010;
8:fen_l=8'b10000000;
9:fen_l=8'b10010000;
default:fen_l=1'bx;
endcase
case(s_4)
0:fen_h=8'b11000000;
1:fen_h=8'b11111001;
2:fen_h=8'b10100100;
3:fen_h=8'b10110000;
4:fen_h=8'b10011001;
5:fen_h=8'b01001001;
6:fen_h=8'b10010010;
default:fen_h=1'bx;
endcase
case(s_6)
0:msec_l=8'b11000000;
1:msec_l=8'b11111001;
2:msec_l=8'b10100100;
3:msec_l=8'b10110000;
4:msec_l=8'b10011001;
5:msec_l=8'b10011001;
6:msec_l=8'b10010010;
7:msec_l=8'b10000010;
8:msec_l=8'b10000000;
9:msec_l=8'b10010000;
default:msec_l=1'bx;
endcase
case(s_5)
0:msec_h=8'b11000000;
1:msec_h=8'b11111001;
2:msec_h=8'b10100100;
3:msec_h=8'b10110000;
4:msec_h=8'b10011001;
5:msec_h=8'b10011001;
6:msec_h=8'b10010010;
7:msec_h=8'b10000010;
8:msec_h=8'b10000000;
9:msec_h=8'b10010000;
default:msec_h=1'bx;
endcase
end
endmodule
//没弄明白
时钟_clock
.//学习数码管显示时钟原理
//视频教程适合我们21EDA电子的所有学习板
module clock(clk,key_in,sm_bit,sm_seg); //模块名clock
input clk; //输入时钟
input[1:0] key_in; //输入按键
output[0:7] sm_bit; //数码管选择输出引脚
output[7:0] sm_seg; //数码管段输出引脚
reg[7:0] sm_seg_r; //定义数码管输出寄存器
reg[7:0] sm_bit_r; //定义数码管选择输出寄存器
reg[3:0] disp_dat; //定义显示数据寄存器
reg[24:0]count; //定义计数寄存器
reg[23:0]hour; //定义现在时刻寄存器
reg sec,keyen; //定义标志位
reg[1:0]dout1,dout2,dout3; //寄存器
wire[1:0]key_done; //按键消抖输出
assign sm_bit = sm_bit_r; //输出数码管选择
assign sm_seg = sm_seg_r; //输出数码管译码结果
//秒信号产生部分
always @(posedge clk) //定义clock上升沿触发
begin
count = count + 1'b1;
if(count == 25'd25000000) //0.5S到了吗?
begin
count = 25'd0; //计数器清零
sec = ~sec; //置位秒标志
end
end
//按键消抖处理部分
assign key_done = (dout1 | dout2 | dout3); //按键消抖输出
always @(posedge count[17])
begin
dout1 <= key_in;
dout2 <= dout1;
dout3 <= dout2;
end
always @(negedge key_done[0])
begin
keyen = ~keyen; //将琴键开关转换为乒乓开关
end
//数码管动态扫描显示部分
always @(posedge clk) //count[17:15]大约1ms改变一次
begin
case(count[17:15]) //选择扫描显示数据
3'd0:disp_dat = hour[3:0]; //秒个位
3'd1:disp_dat = hour[7:4]; //秒十位
3'd2:disp_dat = 4'ha; //显示"-"
3'd3:disp_dat = hour[11:8]; //分个位
3'd4:disp_dat = hour[15:12]; //分十位
3'd5:disp_dat = 4'ha; //显示"-"
3'd6:disp_dat = hour[19:16]; //时个位
3'd7:disp_dat = hour[23:20]; //时十位
endcase
case(count[17:15]) //选择数码管显示位
3'd0:sm_bit_r = 8'b11111110; //选择第一个数码管显示
3'd1:sm_bit_r = 8'b11111101; //选择第二个数码管显示
3'd2:sm_bit_r = 8'b11111011; //选择第三个数码管显示
3'd3:sm_bit_r = 8'b11110111; //选择第四个数码管显示
3'd4:sm_bit_r = 8'b11101111; //选择第五个数码管显示
3'd5:sm_bit_r = 8'b11011111; //选择第六个数码管显示
3'd6:sm_bit_r = 8'b10111111; //选择第七个数码管显示
3'd7:sm_bit_r = 8'b01111111; //选择第八个数码管显示
endcase
end
always @(posedge clk)
begin
case(disp_dat)
4'h0:sm_seg_r = 8'hc0; //显示0
4'h1:sm_seg_r = 8'hf9; //显示1
4'h2:sm_seg_r = 8'ha4; //显示2
4'h3:sm_seg_r = 8'hb0; //显示3
4'h4:sm_seg_r = 8'h99; //显示4
4'h5:sm_seg_r = 8'h92; //显示5
4'h6:sm_seg_r = 8'h82; //显示6
4'h7:sm_seg_r = 8'hf8; //显示7
4'h8:sm_seg_r = 8'h80; //显示8
4'h9:sm_seg_r = 8'h90; //显示9
4'ha:sm_seg_r = 8'hbf; //显示-
default:sm_seg_r = 8'hff; //不显示
endcase
if((count[17:15]== 3'd2)&sec)
sm_seg_r = 8'hff;
end
//计时处理部分
always @(negedge sec or negedge key_done[1])//计时处理
begin
if(!key_done[1]) //是清零键吗?
begin
hour = 24'h0; //是,则清零
end
else if(!keyen)
begin
hour[3:0] = hour[3:0] + 1'b1; //秒加1
if(hour[3:0] == 4'ha)
begin
hour[3:0] = 4'h0;
hour[7:4] = hour[7:4] + 1'b1; //秒的十位加一
if(hour[7:4] == 4'h6)
begin
hour[7:4] = 4'h0;
hour[11:8] = hour[11:8] + 1'b1;//分个位加一
if(hour[11:8] == 4'ha)
begin
hour[11:8] = 4'h0;
hour[15:12] = hour[15:12] + 1'b1;//分十位加一
if(hour[15:12] == 4'h6)
begin
hour[15:12] = 4'h0;
hour[19:16] = hour[19:16] + 1'b1;//时个位加一
if(hour[19:16] == 4'ha)
begin
hour[19:16] = 4'h0;
hour[23:20] = hour[23:20] + 1'b1;//时十位加一
end
if(hour[23:16] == 8'h24)
hour[23:16] = 8'h0;
end
end
end
end
end
end
endmodule
