频分复用
同一个时间共用一个频道,只不过频率不同,所以互不影响
时分复用
不同时间公用一个频道,轮流使用
时分复用(TDM,Time-division multiplexing)就是将提供给整个信道传输信息的时间划分成若干时间片 (简称时隙),并将这些时隙分配给每一个信号源使用,保证资源的利用率。
码分复用
同一时间同一频道,共同使用,但是使用的编码不同,故互不影响
动态显示
就是这一段时间内,要显示0123这个数字,首先是要保证这4个数字不会变动与更新,即处于Refresh period的时间内,然后在这一时间内要保证可以分别显示出这4个数字,即Digit period,为这一段时间内分别亮这4个灯
需要保证不会超过人眼的分辨频率
`timescale 1ns / 1ps
module all_divider(
input clk_i,
output reg clk_o
);
reg [16:0] cnt=0;
always@(posedge clk_i) begin
if(cnt == 99999)
cnt <= 'b000;
else
cnt <= cnt + 1'b1;
if(cnt <= 49999)
clk_o <= 1'b1;
else
clk_o <= 1'b0;
end
endmodule
这个模块的就是把原始始终信号clk转变为
clk只会翻转就是高频率的0_1变换
每次从0到1意味着上一个周期的结束与新一个周期的开始
内部时钟周期为100MHZ
cnt记录的是clk的周期数量,cnt只记录到99999,即1e5次周期
`timescale 1ns / 1ps
module all_counter(
input [7:0]out0,
input [7:0]out1,
input [7:0]out2,
input [7:0]out3,
input [7:0]out4,
input [7:0]out5,
input [7:0]out6,
input [7:0]out7,
input clk_i,
output reg [7:0]left,
output reg [7:0]right,
output reg [3:0]dn0,
output reg [3:0]dn1
);
wire clk_o; //分频后的时钟信号
reg [1:0]count=2'b00; //计数器,控制使能端(相当于一个24译码器)
//分频模块的调用
all_divider div(clk_i,clk_o);
always @(posedge clk_o) begin
if(count == 3) //到3记得将计数器清零即可
begin
count = 2'b00;
left <= out3;
right<= out7;
dn0<=4'b0001;
dn1<=4'b0001;
end
else
begin
case(count) //case语句正常判断使能端的内容
2'b00:
begin
left<=out0;
right<=out4;
dn0<=4'b1000;
dn1<=4'b1000;
end
2'b01:
begin
left<=out1;
right<=out5;
dn0<=4'b0100;
dn1<=4'b0100;
end
2'b10:
begin
left<=out2;
right<=out6;
dn0<=4'b0010;
dn1<=4'b0010;
end
endcase
count = count + 1'b1;
end
end
endmodule
计数器,控制使能端,相当于一个二四译码器,就是控制四个灯哪个灯亮
上面的分频是把信号控制在人眼检测不到的程度,下面计数器也是一个分频,每4个分频后的小周期组成一个大周期,这个大周期就是每组数的持续时间,就是要保证每组数在这个大周期内不发生变化,才能保证在这个大周期里的四个四分之一小周期才可以完整显示出这组数
计时器
还是需要进行分频,并且我们需要有复位端。
输入:时钟信号和复位使能端
输出:两个八位二进制数(控制前两个的)
这里的divider是要把系统时钟周期转变为1HZ的,就是一秒一周期,这样才可以计时
而之前的all_divider是把系统时钟周期转变为小周期,并非计时用
`timescale 1ns / 1ps
module counter(
input clk_i,
input s,
output reg [7:0]out0,
output reg [7:0]out1
);
wire clk;
reg [3:0]middle=4'b1010;//计数器,从10开始
divider div(clk_i,clk);
always @(posedge s or posedge clk) begin
if(s) //复位使能端有效
begin
middle = 10;
out0 = 8'b0110_0000; //1
out1 = 8'b1111_1100; //0
end
else if(middle==0) //到0了,重新开始计数
begin
middle = 10;
out0 = 8'b0110_0000;
out1 = 8'b1111_1100;
end
else
begin
middle = middle - 1'b1;
out0 = 8'b1111_1100; //高位为0
case(middle)
4'b0000:out1 = 8'b1111_1100; //按照计数器内容控制
4'b0001:out1 = 8'b0110_0000;
4'b0010:out1 = 8'b1101_1010;
4'b0011:out1 = 8'b1111_0010;
4'b0100:out1 = 8'b0110_0110;
4'b0101:out1 = 8'b1011_0110;
4'b0110:out1 = 8'b1011_1110;
4'b0111:out1 = 8'b1110_0000;
4'b1000:out1 = 8'b1111_1110;
4'b1001:out1 = 8'b1111_0110;
4'b1010:out1 = 8'b1111_1100;
endcase
end
end
endmodule
这里计时器的实现就是把1Hz的时钟信号通过中间量middle连接起来,当时钟上升沿来临时,mid改变一次,然后mid的改变使数码管接收到的信号发生改变,
(这里的代码有一点不怎么规范,应该都采用非阻塞赋值的,但是因为使能端需要立即改变,而如果是非阻塞则需要等到下一个always块,会相对慢一个周期)
之所以输出8位的二进制数,是因为采用的是七段数码管+一个点,所以一共八位
然后又由于有8个数码管,所以一共有0~7个output,这里采用的是把8个分为两组,即左右两组开始展示,而不是8个合在一起依次展示,不然时间周期太大
控制四位拨码开关
这个比较简单,就是一个4-16译码器,直接上代码:
`timescale 1ns / 1ps
module four(
input [3:0] in,
output reg [7:0] out
);
always@(*) begin
case(in)
4'b0000:out=8'b1111_1100;
4'b0001:out=8'b0110_0000;
4'b0010:out=8'b1101_1010;
4'b0011:out=8'b1111_0010;
4'b0100:out=8'b0110_0110;
4'b0101:out=8'b1011_0110;
4'b0110:out=8'b1011_1110;
4'b0111:out=8'b1110_0000;
4'b1000:out=8'b1111_1110;
4'b1001:out=8'b1111_0110;
4'b1010:out=8'b1110_1110;
4'b1011:out=8'b0011_1110;
4'b1100:out=8'b0001_1010;
4'b1101:out=8'b0111_1010;
4'b1110:out=8'b1001_1110;
4'b1111:out=8'b1000_1110;
endcase
end
endmodule
然后使用一个顶层模块串起来就行了:
`timescale 1ns / 1ps
module hexseg8(
input s,
input [3:0]sw1,
input [3:0]sw2,
input clk_i,
output wire [7:0]left,
output wire [7:0]right,
output wire [3:0]dn0,
output wire [3:0]dn1
);
wire [7:0]out0;
wire [7:0]out1;
wire [7:0]out2;
wire [7:0]out3;//前4个是变化的时间
wire [7:0]out4=8'b; //班级
wire [7:0]out5=8'b; //班级(记得加小数点
wire [7:0]out6=8'b; //学号
wire [7:0]out7=8'b;
wire [15:0]temp=0;
//四位拨码开关
four four1(sw1,out3);
four four2(sw2,out2);
//计数器
counter counter1(clk_i,s,out0,out1);
//数码管显示分频模块
all_counter counter2(out0,out1,out2,out3,out4,out5,out6,out7,clk_i,left,right,dn0,dn1);
endmodule
整体的思路应该是,系统时钟信号导进来,然后经过分频器处理为1HZ时钟信号,接着再经过时钟处理模板,转化为显示的信号,再到显示模板,进行显示
即一共需要三个模板
第一个模板是分频器,输入是系统时钟,输出是1HZ时钟
第二个模板是时钟信号处理模板,不断输入1HZ时钟信号,表示计时,不断输出显示的信号
具体来说就是1个输入,然后输出6个8位的信号,一二位是秒信号,三四位为分钟信号,五六位为小时信号(八位是因为有小数点,就是最右位,由于没有用,所以一直是0)
第三个模板是显示模板,显示是要分时复用,输入是6个8位的信号
数码管不能同时亮是因为4个数码管是串接在一起的,如果同时亮,那么产生的控制信号同时控制4个数码管,即四个数码管显示的是同一个内容,所以需要控制每次只亮一个,4个里只亮1个,亮的就是控制它亮的部分。
而LED是并连在一起的,也就是说,LED各自有控制信号,所以不会互相影响,可以同时亮,而数码管不可以
而且显示要求,4个数码管量,8个Led灯(4个为一组显示小时信号)
就是说,需要输出1个四位的信号(表示数码管上的使能信号,决定此时是哪个数码管在亮),1个八位的信号(表示那个亮的数码管显示什么内容的信号),1个八位的信号(表示LED亮的信号,是表示小时的信号)
LED不需要使能信号是因为LED可以同时亮,直接把8位的信号对应到下面的LED上即可
首先是要有一个计数器,周期为1HZ,有4个数码管,就表示分和秒
然后小时就表示在led灯上,十六进制就是说,每4个led组成一组来表示小时,4个一组可以表示到16个小时
所以8个led可以表示32个小时
?怎么实现秒到分,分到时?
思路应该是确定三组信号,一组表示秒,一组表示分,一组表示小时
表示秒的信号到60时,让分的信号+1,
表示分的信号到60时,让小时的信号+1
小时的信号是
这个时间就是拆出5位,第一位是10进制,如果第一位到了10,第二位加一,第二位到了6,归零,第三位加一,第三位到了10,第四位加一,第四位到了六,第五位加一,第五位就不再进位
然后数码管要接收的显示信号,就直接读取前四位的结果进行转化
进位应该是再加的时候,如果到9了,就置为0,往高位进一,
produce_clk用来产生实际的时钟信号,并把时钟信号转化为数码管所需要的信号,即输出Output
是在顶层文件里调用
presentation_Hz是分系统时钟频率为显示频率,不在顶层文件中调用,在数码管显示文件里调用
hz1clk是分频为实际频率,在produce_clk里调用
只产生信号还不够,还需要分时复用地去显示信号,就是all_counter文件调用,
all_counter接收produce_clk产生的信号,分时复用地显示信号,在顶层文件里调用
produce_clk的信号改变周期是1HZ,all_counter的刷新频率为显示频率的四倍,远远高于信号更新频率
这里输入有两个信号,输出有3个信号,需要分配2(输入,一个开关,一个时钟信号)+8(数码管引脚)+4(数码管编号)+8(8个LED)=22个引脚
module display_7seg(
input CLK,
input SW_in,
output reg[10:0] display_out
);
reg [19:0]count=0;
reg [2:0] sel=0;
parameter T1MS=50000;
always@(posedge CLK)
begin
if(SW_in==0)
begin
case(sel)
0:display_out<=11'b0111_1001111;
1:display_out<=11'b1011_0010010;
2:display_out<=11'b1101_0000110;
3:display_out<=11'b1110_1001100;
default:display_out<=11'b1111_1111111;
endcase
end
else
begin
case(sel)
0:display_out<=11'b1110_1001111;
1:display_out<=11'b1101_0010010;
2:display_out<=11'b1011_0000110;
3:display_out<=11'b0111_1001100;
default:display_out<=11'b1111_1111111;
endcase
end
end
always@(posedge CLK)
begin
count<=count+1;
if(count==T1MS)
begin
count<=0;
sel<=sel+1;
if(sel==4)
sel<=0;
end
end
endmodule
这里要CLK,sw_in,display_out0~10的信号,就是顶层文件所涉及到的信号(输入输出),
中间的辅助信号是不需要的,比如count,sel之类的,只是输入和输出
自左到右为a~g,就是presentation[0]为g
set_property PACKAGE_PIN[get_ports]
set_property IOSTANDARD LCVMOSS[get_ports ]
set_property PACKAGE_PIN W5 [get_ports CLK]
set_property PACKAGE_PIN V17 [get_ports SW_in]
set_property IOSTANDARD LVCMOS33 [get_ports SW_in]
set_property IOSTANDARD LVCMOS33 [get_ports CLK]
set_property PACKAGE_PIN W4 [get_ports {display_out[10]}]
set_property PACKAGE_PIN V4 [get_ports {display_out[9]}]
set_property PACKAGE_PIN U4 [get_ports {display_out[8]}]
set_property PACKAGE_PIN U2 [get_ports {display_out[7]}]
set_property PACKAGE_PIN W7 [get_ports {display_out[6]}]
set_property PACKAGE_PIN W6 [get_ports {display_out[5]}]
set_property PACKAGE_PIN U8 [get_ports {display_out[4]}]
set_property PACKAGE_PIN V8 [get_ports {display_out[3]}]
set_property PACKAGE_PIN U5 [get_ports {display_out[2]}]
set_property PACKAGE_PIN V5 [get_ports {display_out[1]}]
set_property PACKAGE_PIN U7 [get_ports {display_out[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display_out[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display_out[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display_out[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display_out[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display_out[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display_out[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display_out[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display_out[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display_out[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display_out[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display_out[10]}]
set_property -dict{PACKAGE_PIN R2 IOSTANDARD LVCMOS33}[get_ports s]
set_property -dict{PACKAGE_PIN W5 IOSTANDARD LVCMOS33}[get_ports clk_i]
set_property -dict{PACKAGE_PIN U7 IOSTANDARD LVCMOS33}[get_ports{presentation[0]}]
set_property -dict{PACKAGE_PIN V5 IOSTANDARD LVCMOS33}[get_ports{presentation[1]}]
set_property -dict{PACKAGE_PIN U5 IOSTANDARD LVCMOS33}[get_ports{presentation[2]}]
set_property -dict{PACKAGE_PIN V8 IOSTANDARD LVCMOS33}[get_ports{presentation[3]}]
set_property -dict{PACKAGE_PIN U8 IOSTANDARD LVCMOS33}[get_ports{presentation[4]}]
set_property -dict{PACKAGE_PIN W6 IOSTANDARD LVCMOS33}[get_ports{presentation[5]}]
set_property -dict{PACKAGE_PIN W7 IOSTANDARD LVCMOS33}[get_ports{presentation[6]}]
set_property -dict{PACKAGE_PIN U2 IOSTANDARD LVCMOS33}[get_ports{dn0[0]}]
set_property -dict{PACKAGE_PIN U4 IOSTANDARD LVCMOS33}[get_ports{dn0[1]}]
set_property -dict{PACKAGE_PIN V4 IOSTANDARD LVCMOS33}[get_ports{dn0[2]}]
set_property -dict{PACKAGE_PIN W4 IOSTANDARD LVCMOS33}[get_ports{dn0[3]}]
set_property -dict{PACKAGE_PIN V13 IOSTANDARD LVCMOS33}[get_ports{hour[0]}]
set_property -dict{PACKAGE_PIN V3 IOSTANDARD LVCMOS33}[get_ports{hour[1]}]
set_property -dict{PACKAGE_PIN W3 IOSTANDARD LVCMOS33}[get_ports{hour[2]}]
set_property -dict{PACKAGE_PIN U3 IOSTANDARD LVCMOS33}[get_ports{hour[3]}]
set_property -dict{PACKAGE_PIN P3 IOSTANDARD LVCMOS33}[get_ports{hour[4]}]
set_property -dict{PACKAGE_PIN N3 IOSTANDARD LVCMOS33}[get_ports{hour[5]}]
set_property -dict{PACKAGE_PIN P1 IOSTANDARD LVCMOS33}[get_ports{hour[6]}]
set_property -dict{PACKAGE_PIN L1 IOSTANDARD LVCMOS33}[get_ports{hour[7]}]