实验题目:移位显示“Hello”字符串(开发板上有6个数码管):
设计基本要求: (1)复位信号高电平有效由滑动开关送入,下降沿的同时右对齐显示“Hello”字符, 并由右向左移动,空两格循环显示;
(2)按键触发单稳态定时,字符由左向右逆向循环,定时结束后恢复(定时为5s);
(3)按键控制位移步进速度,至少三个不同值。
设计进阶: (4)使用同一按键控制步进速度;
视频展示:
链接:https://pan.baidu.com/s/1OEkvViKP239-_0miCaBeBg
提取码:0uup
采用top-down设计;
module div(clock_in,clock_out);//先做个时钟分频模块
input clock_in;
output clock_out;
reg clk_p_r;
reg clk_n_r;
reg [F_DIV_WIDTH-1:0] count_p;
reg [F_DIV_WIDTH-1:0] count_n;
parameter F_DIV=48000000;//分频参数设置,因为本人开发板晶振时钟为50MHz,当此值为50000000时,可得1Hz频率
parameter F_DIV_WIDTH=32;//
wire full_div_p;
wire half_div_p;
wire full_div_n;
wire half_div_n;
assign full_div_p = (count_p<F_DIV-1);
assign half_div_p = (count_p<(F_DIV>>1)-1);
assign full_div_n = (count_p<F_DIV-1);
assign half_div_n = (count_p<(F_DIV>>1)-1);
assign clock_out = (F_DIV==1)? clock_in:(F_DIV[0]? (clk_p_r&clk_n_r):clk_p_r);
always @(posedge clock_in)
begin
if(full_div_p)
begin
count_p=count_p+1'b1;
if(half_div_p)
clk_p_r=1'b0;
else
clk_p_r=1'b1;
end
else
begin
count_p=0;
clk_p_r=1'b0;
end
end
always@(negedge clock_in)
begin
if(full_div_n)
begin
count_n=count_n+1'b1;
if(half_div_n)
clk_n_r=1'b0;
else
clk_n_r=1'b1;
end
else
begin
count_n=0;
clk_n_r=1'b0;
end
end
endmodule
module State_left(clk,rst,in,Stateout5,Stateout4,Stateout3,Stateout2,Stateout1,Stateout0);//数码管正循环(从右向左移动)状态机模块
input clk,rst;
input in;//由同一个按键控制的步进速度信号
output [2:0] Stateout5,Stateout4,Stateout3,Stateout2,Stateout1,Stateout0;//输出6个数码管的状态变化
reg [2:0] Stateout5,Stateout4,Stateout3,Stateout2,Stateout1,Stateout0;
reg [25:0]Time1;
reg [1:0] Speed;
reg [25:0]Count5,Count4,Count3,Count2,Count1,Count0;
wire clk_1Hz;
div #(50000000,32) nclk(clk,clk_1Hz);
always@(posedge clk_1Hz)//步进速度信号控制,每按一次按键,速度逐渐加快。
begin
if(rst==1)
Speed=2'd0;
else
begin
if(in)
begin
if(Speed==2'd3)
Speed=2'd0;
else
Speed=Speed+1'b1;
end
else
Speed=Speed;
end
end
always@(posedge clk)
begin
case(Speed)//内置步进速度自定义设置
2'b00:Time1=26'd50000000;//1Hz(1s一格)
2'b01:Time1=26'd20000000;//2.5Hz(0.4s一格)
2'b10:Time1=26'd5000000;//10Hz(0.1s一格)
2'b11:Time1=26'd1000000;//50Hz(0.02s一格)
endcase
end
always@(posedge clk)//右起第一个数码管的状态机循环,初始值为Stateout=3'b100,显示字母为“O”
begin
if (rst==1)
Stateout0=3'b100;
else
begin
if(Count0==Time1)
begin
Count0=26'd0;
if(Stateout0==3'b110)
Stateout0=3'b000;
else
Stateout0=Stateout0+3'b001;
end
else
begin
Count0=Count0+1'b1;
Stateout0=Stateout0;
end
end
end
always@(posedge clk)//右起第二个数码管的状态机循环,初始值为Stateout=3'b011,显示字母为“L”
begin
if (rst==1)
Stateout1=3'b011;
else
begin
if(Count1==Time1)
begin
Count1=26'd0;
if(Stateout1==3'b110)
Stateout1=3'b000;
else
Stateout1=Stateout1+3'b001;
end
else
begin
Count1=Count1+1'b1;
Stateout1=Stateout1;
end
end
end
always@(posedge clk)//右起第三个数码管的状态机循环,初始值为Stateout=3'b010,显示字母为“L”
begin
if (rst==1)
Stateout2=3'b010;
else
begin
if(Count2==Time1)
begin
Count2=26'd0;
if(Stateout2==3'b110)
Stateout2=3'b000;
else
Stateout2=Stateout2+3'b001;
end
else
begin
Count2=Count2+1'b1;
Stateout2=Stateout2;
end
end
end
always@(posedge clk)//右起第四个数码管的状态机循环,初始值为Stateout=3'b001,显示字母为“E”
begin
if (rst==1)
Stateout3=3'b001;
else
begin
if(Count3==Time1)
begin
Count3=26'd0;
if(Stateout3==3'b110)
Stateout3=3'b000;
else
Stateout3=Stateout3+3'b001;
end
else
begin
Count3=Count3+1'b1;
Stateout3=Stateout3;
end
end
end
always@(posedge clk)//右起第五个数码管的状态机循环,初始值为Stateout=3'b000,显示为“H”
begin
if (rst==1)
Stateout4=3'b000;
else
begin
if(Count4==Time1)
begin
Count4=26'd0;
if(Stateout4==3'b110)
Stateout4=3'b000;
else
Stateout4=Stateout4+3'b001;
end
else
begin
Count4=Count4+1'b1;
Stateout4=Stateout4;
end
end
end
always@(posedge clk)//右起第六个数码管的状态机循环,初始值为Stateout=3'b110,显示字母为“空”
begin
if (rst==1)
Stateout5=3'b110;
else
begin
if(Count5==Time1)
begin
Count5=26'd0;
if(Stateout5==3'b110)
Stateout5=3'b000;
else
Stateout5=Stateout5+3'b001;
end
else
begin
Count5=Count5+1'b1;
Stateout5=Stateout5;
end
end
end
endmodule
module State_right(clk,rst,Stateout5,Stateout4,Stateout3,Stateout2,Stateout1,Stateout0);//单稳态逆循环数码管状态机模块
input clk,rst;
output [2:0] Stateout5,Stateout4,Stateout3,Stateout2,Stateout1,Stateout0;//输出6个数码管的状态变化
reg [2:0] Stateout5,Stateout4,Stateout3,Stateout2,Stateout1,Stateout0;
parameter Time1=26'd25000000;//设置分频参数,固定步进速度。
reg [25:0]Count5,Count4,Count3,Count2,Count1,Count0;
always@(posedge clk)//右起第一个数码管的状态机循环,初始值为Stateout=3'b101,显示字母为“空”
begin
if (rst==1)
Stateout0=3'b101;
else
begin
if(Count0==Time1)
begin
Count0=26'd0;
if(Stateout0==3'b000)
Stateout0=3'b110;
else
Stateout0=Stateout0-3'b001;
end
else
begin
Count0=Count0+1'b1;
Stateout0=Stateout0;
end
end
end
always@(posedge clk)//右起第二个数码管的状态机循环,初始值为Stateout=3'b100,显示字母为“O”
begin
if (rst==1)
Stateout1=3'b100;
else
begin
if(Count1==Time1)
begin
Count1=26'd0;
if(Stateout1==3'b000)
Stateout1=3'b110;
else
Stateout1=Stateout1-3'b001;
end
else
begin
Count1=Count1+1'b1;
Stateout1=Stateout1;
end
end
end
always@(posedge clk)//右起第三个数码管的状态机循环,初始值为Stateout=3'b011,显示字母为“L”
begin
if (rst==1)
Stateout2=3'b011;
else
begin
if(Count2==Time1)
begin
Count2=26'd0;
if(Stateout2==3'b000)
Stateout2=3'b110;
else
Stateout2=Stateout2-3'b001;
end
else
begin
Count2=Count2+1'b1;
Stateout2=Stateout2;
end
end
end
always@(posedge clk)//右起第四个数码管的状态机循环,初始值为Stateout=3'b010,显示字母为“L”
begin
if (rst==1)
Stateout3=3'b010;
else
begin
if(Count3==Time1)
begin
Count3=26'd0;
if(Stateout3==3'b000)
Stateout3=3'b110;
else
Stateout3=Stateout3-3'b001;
end
else
begin
Count3=Count3+1'b1;
Stateout3=Stateout3;
end
end
end
always@(posedge clk)//右起第五个数码管的状态机循环,初始值为Stateout=3'b001,显示为“E”
begin
if (rst==1)
Stateout4=3'b001;
else
begin
if(Count4==Time1)
begin
Count4=26'd0;
if(Stateout4==3'b000)
Stateout4=3'b110;
else
Stateout4=Stateout4-3'b001;
end
else
begin
Count4=Count4+1'b1;
Stateout4=Stateout4;
end
end
end
always@(posedge clk)//右起第六个数码管的状态机循环,初始值为Stateout=3'b000,显示字母为“H”
begin
if (rst==1)
Stateout5=3'b000;
else
begin
if(Count5==Time1)
begin
Count5=26'd0;
if(Stateout5==3'b00)
Stateout5=3'b110;
else
Stateout5=Stateout5-3'b001;
end
else
begin
Count5=Count5+1'b1;
Stateout5=Stateout5;
end
end
end
endmodule
module Display(clk,rst,Stateout5,Stateout4,Stateout3,Stateout2,
Stateout1,Stateout0,DigtronCS_out,Digtron_out);//数码管扫描驱动显示模块
input clk,rst;
input [2:0] Stateout5,Stateout4,Stateout3,Stateout2,Stateout1,Stateout0;
output [5:0] DigtronCS_out;//输出七段数码管的八位字码段显示信号
output [7:0] Digtron_out;//输出六个数码管的六位片选信号
reg [7:0] Digtron_out;
reg [5:0] DigtronCS_out;
reg [2:0] dis;
parameter Timex=8'd200;//设置扫描显示频率为250kHz
reg [7:0] Count;
always@(posedge clk)
begin
if(rst==1)
DigtronCS_out=6'b111110;
else
begin
if(Count==Timex)
begin
Count=8'd0;
DigtronCS_out={DigtronCS_out[4:0],DigtronCS_out[5]};//数码管片选扫描驱动状态机循环
end
else
begin
Count=Count+1'b1;
DigtronCS_out=DigtronCS_out;
end
end
end
always@( posedge clk)
begin
case(DigtronCS_out)
6'b111110:dis=Stateout0;
6'b111101:dis=Stateout1;
6'b111011:dis=Stateout2;
6'b110111:dis=Stateout3;
6'b101111:dis=Stateout4;
6'b011111:dis=Stateout5;
endcase
end
always@(posedge clk) //数码管不同的状态对应字段显示的字母编码
begin
case(dis)
3'b000:Digtron_out=8'h6e;//字母“H”
3'b001:Digtron_out=8'h9e;//字母“E”
3'b010:Digtron_out=8'h1c;//字母“L”
3'b011:Digtron_out=8'h1c;//字母“L”
3'b100:Digtron_out=8'hfc;//字母“0”
3'b101:Digtron_out=8'h00;//空
3'b110:Digtron_out=8'h00;//空
endcase
end
endmodule
module select_dir(clk,in,S25,S24,S23,S22,S21,S20,S15,S14,S13,S12,S11,S10,S5,S4,S3,S2,S1,S0);//移动方向选择模块
input clk,in;
input [2:0] S25,S24,S23,S22,S21,S20,S15,S14,S13,S12,S11,S10;
output [2:0] S5,S4,S3,S2,S1,S0;
reg [2:0] S5,S4,S3,S2,S1,S0;
wire clk_1Hz;
reg[4:0] count;
div #(50000000,32) nclk(clk,clk_1Hz);//设置频率为1S;
always@(posedge clk_1Hz)
begin
if(in==1'b1)//in输入时,开始计时
count=count+1'b1;
else
count=5'd0; //in无输入时,为初始状态
end
always@(posedge clk)
begin
if(count==5'd0)//初始状态为正循环
begin
S5=S15;
S4=S14;
S3=S13;
S2=S12;
S1=S11;
S0=S10;
end
else
begin
if(count<=5'd10)//每当计时不到5s的时候,启动单稳态逆循环
begin
S5=S25;
S4=S24;
S3=S23;
S2=S22;
S1=S21;
S0=S20;
end
else //单稳态逆循环定时时间为5s,计时超过5s,自动返回到正循环
begin
S5=S15;
S4=S14;
S3=S13;
S2=S12;
S1=S11;
S0=S10;
end
end
end
endmodule
module Hello(clk,rst,in0,in1,DigtronCS_out,Digtron_out);//顶层文件
input clk,rst,in0,in1;
output [5:0] DigtronCS_out;
output [7:0] Digtron_out;
wire[2:0] S15,S14,S13,S12,S11,S10;
wire [2:0] S25,S24,S23,S22,S21,S20;
wire [2:0] S5,S4,S3,S2,S1,S0;
State_left u1(clk,rst,~in0,S15,S14,S13,S12,S11,S10);//正循环数码管状态机模块
State_right u2(clk,rst,S25,S24,S23,S22,S21,S20);//单稳态逆循环数码管状态机模块
select_dir u3(clk,in1,S25,S24,S23,S22,S21,S20,S15,S14,S13,S12,S11,S10,S5,S4,S3,S2,S1,S0);//方向选择模块
Display u4(clk,rst,S5,S4,S3,S2,S1,S0,DigtronCS_out,Digtron_out);//数码管显示模块
endmodule