• 10.18~10.22数电第二次实验


    频分复用

    同一个时间共用一个频道,只不过频率不同,所以互不影响

    时分复用

    不同时间公用一个频道,轮流使用

    时分复用TDM,Time-division multiplexing)就是将提供给整个信道传输信息的时间划分成若干时间片 (简称时隙),并将这些时隙分配给每一个信号源使用,保证资源的利用率。

    码分复用

    同一时间同一频道,共同使用,但是使用的编码不同,故互不影响

    动态显示

    就是这一段时间内,要显示0123这个数字,首先是要保证这4个数字不会变动与更新,即处于Refresh period的时间内,然后在这一时间内要保证可以分别显示出这4个数字,即Digit period,为这一段时间内分别亮这4个灯

    需要保证不会超过人眼的分辨频率

    1. `timescale 1ns / 1ps
    2. module all_divider(
    3.     input clk_i,
    4.     output reg clk_o
    5.     );
    6.     reg [16:0] cnt=0;
    7.     always@(posedge clk_i) begin
    8.     if(cnt == 99999)
    9.         cnt <= 'b000;
    10.     else 
    11.         cnt <= cnt + 1'b1;
    12.     
    13.     if(cnt <= 49999)
    14.         clk_o <= 1'b1;
    15.     else 
    16.         clk_o <= 1'b0;
    17.     end
    18. endmodule

    这个模块的就是把原始始终信号clk转变为

    clk只会翻转就是高频率的0_1变换

    每次从0到1意味着上一个周期的结束与新一个周期的开始

    内部时钟周期为100MHZ

    cnt记录的是clk的周期数量,cnt只记录到99999,即1e5次周期

    1. `timescale 1ns / 1ps
    2. module all_counter(
    3. input [7:0]out0,
    4. input [7:0]out1,
    5. input [7:0]out2,
    6. input [7:0]out3,
    7. input [7:0]out4,
    8. input [7:0]out5,
    9. input [7:0]out6,
    10. input [7:0]out7,
    11. input clk_i,
    12. output reg [7:0]left,
    13. output reg [7:0]right,
    14. output reg [3:0]dn0,
    15. output reg [3:0]dn1
    16. );
    17. wire clk_o; //分频后的时钟信号
    18. reg [1:0]count=2'b00; //计数器,控制使能端(相当于一个24译码器)
    19. //分频模块的调用
    20. all_divider div(clk_i,clk_o);
    21. always @(posedge clk_o) begin
    22. if(count == 3) //到3记得将计数器清零即可
    23. begin
    24. count = 2'b00;
    25. left <= out3;
    26. right<= out7;
    27. dn0<=4'b0001;
    28. dn1<=4'b0001;
    29. end
    30. else
    31. begin
    32. case(count) //case语句正常判断使能端的内容
    33. 2'b00:
    34. begin
    35. left<=out0;
    36. right<=out4;
    37. dn0<=4'b1000;
    38. dn1<=4'b1000;
    39. end
    40. 2'b01:
    41. begin
    42. left<=out1;
    43. right<=out5;
    44. dn0<=4'b0100;
    45. dn1<=4'b0100;
    46. end
    47. 2'b10:
    48. begin
    49. left<=out2;
    50. right<=out6;
    51. dn0<=4'b0010;
    52. dn1<=4'b0010;
    53. end
    54. endcase
    55. count = count + 1'b1;
    56. end
    57. end
    58. endmodule

    计数器,控制使能端,相当于一个二四译码器,就是控制四个灯哪个灯亮

    上面的分频是把信号控制在人眼检测不到的程度,下面计数器也是一个分频,每4个分频后的小周期组成一个大周期,这个大周期就是每组数的持续时间,就是要保证每组数在这个大周期内不发生变化,才能保证在这个大周期里的四个四分之一小周期才可以完整显示出这组数

    计时器
    还是需要进行分频,并且我们需要有复位端。
    输入:时钟信号和复位使能端
    输出:两个八位二进制数(控制前两个的) 

    这里的divider是要把系统时钟周期转变为1HZ的,就是一秒一周期,这样才可以计时

    而之前的all_divider是把系统时钟周期转变为小周期,并非计时用

    1. `timescale 1ns / 1ps
    2. module counter(
    3. input clk_i,
    4. input s,
    5. output reg [7:0]out0,
    6. output reg [7:0]out1
    7. );
    8. wire clk;
    9. reg [3:0]middle=4'b1010;//计数器,从10开始
    10. divider div(clk_i,clk);
    11. always @(posedge s or posedge clk) begin
    12. if(s) //复位使能端有效
    13. begin
    14. middle = 10;
    15. out0 = 8'b0110_0000; //1
    16. out1 = 8'b1111_1100; //0
    17. end
    18. else if(middle==0) //到0了,重新开始计数
    19. begin
    20. middle = 10;
    21. out0 = 8'b0110_0000;
    22. out1 = 8'b1111_1100;
    23. end
    24. else
    25. begin
    26. middle = middle - 1'b1;
    27. out0 = 8'b1111_1100; //高位为0
    28. case(middle)
    29. 4'b0000:out1 = 8'b1111_1100; //按照计数器内容控制
    30. 4'b0001:out1 = 8'b0110_0000;
    31. 4'b0010:out1 = 8'b1101_1010;
    32. 4'b0011:out1 = 8'b1111_0010;
    33. 4'b0100:out1 = 8'b0110_0110;
    34. 4'b0101:out1 = 8'b1011_0110;
    35. 4'b0110:out1 = 8'b1011_1110;
    36. 4'b0111:out1 = 8'b1110_0000;
    37. 4'b1000:out1 = 8'b1111_1110;
    38. 4'b1001:out1 = 8'b1111_0110;
    39. 4'b1010:out1 = 8'b1111_1100;
    40. endcase
    41. end
    42. end
    43. endmodule

    这里计时器的实现就是把1Hz的时钟信号通过中间量middle连接起来,当时钟上升沿来临时,mid改变一次,然后mid的改变使数码管接收到的信号发生改变, 

     (这里的代码有一点不怎么规范,应该都采用非阻塞赋值的,但是因为使能端需要立即改变,而如果是非阻塞则需要等到下一个always块,会相对慢一个周期)

    之所以输出8位的二进制数,是因为采用的是七段数码管+一个点,所以一共八位

    然后又由于有8个数码管,所以一共有0~7个output,这里采用的是把8个分为两组,即左右两组开始展示,而不是8个合在一起依次展示,不然时间周期太大 

    控制四位拨码开关
    这个比较简单,就是一个4-16译码器,直接上代码:

    1. `timescale 1ns / 1ps
    2. module four(
    3. input [3:0] in,
    4. output reg [7:0] out
    5. );
    6. always@(*) begin
    7. case(in)
    8. 4'b0000:out=8'b1111_1100;
    9. 4'b0001:out=8'b0110_0000;
    10. 4'b0010:out=8'b1101_1010;
    11. 4'b0011:out=8'b1111_0010;
    12. 4'b0100:out=8'b0110_0110;
    13. 4'b0101:out=8'b1011_0110;
    14. 4'b0110:out=8'b1011_1110;
    15. 4'b0111:out=8'b1110_0000;
    16. 4'b1000:out=8'b1111_1110;
    17. 4'b1001:out=8'b1111_0110;
    18. 4'b1010:out=8'b1110_1110;
    19. 4'b1011:out=8'b0011_1110;
    20. 4'b1100:out=8'b0001_1010;
    21. 4'b1101:out=8'b0111_1010;
    22. 4'b1110:out=8'b1001_1110;
    23. 4'b1111:out=8'b1000_1110;
    24. endcase
    25. end
    26. endmodule

    然后使用一个顶层模块串起来就行了:

    1. `timescale 1ns / 1ps
    2. module hexseg8(
    3. input s,
    4. input [3:0]sw1,
    5. input [3:0]sw2,
    6. input clk_i,
    7. output wire [7:0]left,
    8. output wire [7:0]right,
    9. output wire [3:0]dn0,
    10. output wire [3:0]dn1
    11. );
    12. wire [7:0]out0;
    13. wire [7:0]out1;
    14. wire [7:0]out2;
    15. wire [7:0]out3;//4个是变化的时间
    16. wire [7:0]out4=8'b; //班级
    17. wire [7:0]out5=8'b; //班级(记得加小数点
    18. wire [7:0]out6=8'b; //学号
    19. wire [7:0]out7=8'b;
    20. wire [15:0]temp=0;
    21. //四位拨码开关
    22. four four1(sw1,out3);
    23. four four2(sw2,out2);
    24. //计数器
    25. counter counter1(clk_i,s,out0,out1);
    26. //数码管显示分频模块
    27. all_counter counter2(out0,out1,out2,out3,out4,out5,out6,out7,clk_i,left,right,dn0,dn1);
    28. 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个引脚 

    1. module display_7seg(
    2. input CLK,
    3. input SW_in,
    4. output reg[10:0] display_out
    5. );
    6. reg [19:0]count=0;
    7. reg [2:0] sel=0;
    8. parameter T1MS=50000;
    9. always@(posedge CLK)
    10. begin
    11. if(SW_in==0)
    12. begin
    13. case(sel)
    14. 0:display_out<=11'b0111_1001111;
    15. 1:display_out<=11'b1011_0010010;
    16. 2:display_out<=11'b1101_0000110;
    17. 3:display_out<=11'b1110_1001100;
    18. default:display_out<=11'b1111_1111111;
    19. endcase
    20. end
    21. else
    22. begin
    23. case(sel)
    24. 0:display_out<=11'b1110_1001111;
    25. 1:display_out<=11'b1101_0010010;
    26. 2:display_out<=11'b1011_0000110;
    27. 3:display_out<=11'b0111_1001100;
    28. default:display_out<=11'b1111_1111111;
    29. endcase
    30. end
    31. end
    32. always@(posedge CLK)
    33. begin
    34. count<=count+1;
    35. if(count==T1MS)
    36. begin
    37. count<=0;
    38. sel<=sel+1;
    39. if(sel==4)
    40. sel<=0;
    41. end
    42. end
    43. endmodule

    这里要CLK,sw_in,display_out0~10的信号,就是顶层文件所涉及到的信号(输入输出),

    中间的辅助信号是不需要的,比如count,sel之类的,只是输入和输出 

    自左到右为a~g,就是presentation[0]为g

    1. set_property PACKAGE_PIN[get_ports]
    2. set_property IOSTANDARD LCVMOSS[get_ports ]
    1. set_property PACKAGE_PIN W5 [get_ports CLK]
    2. set_property PACKAGE_PIN V17 [get_ports SW_in]
    3. set_property IOSTANDARD LVCMOS33 [get_ports SW_in]
    4. set_property IOSTANDARD LVCMOS33 [get_ports CLK]
    5. set_property PACKAGE_PIN W4 [get_ports {display_out[10]}]
    6. set_property PACKAGE_PIN V4 [get_ports {display_out[9]}]
    7. set_property PACKAGE_PIN U4 [get_ports {display_out[8]}]
    8. set_property PACKAGE_PIN U2 [get_ports {display_out[7]}]
    9. set_property PACKAGE_PIN W7 [get_ports {display_out[6]}]
    10. set_property PACKAGE_PIN W6 [get_ports {display_out[5]}]
    11. set_property PACKAGE_PIN U8 [get_ports {display_out[4]}]
    12. set_property PACKAGE_PIN V8 [get_ports {display_out[3]}]
    13. set_property PACKAGE_PIN U5 [get_ports {display_out[2]}]
    14. set_property PACKAGE_PIN V5 [get_ports {display_out[1]}]
    15. set_property PACKAGE_PIN U7 [get_ports {display_out[0]}]
    16. set_property IOSTANDARD LVCMOS33 [get_ports {display_out[9]}]
    17. set_property IOSTANDARD LVCMOS33 [get_ports {display_out[8]}]
    18. set_property IOSTANDARD LVCMOS33 [get_ports {display_out[7]}]
    19. set_property IOSTANDARD LVCMOS33 [get_ports {display_out[6]}]
    20. set_property IOSTANDARD LVCMOS33 [get_ports {display_out[5]}]
    21. set_property IOSTANDARD LVCMOS33 [get_ports {display_out[4]}]
    22. set_property IOSTANDARD LVCMOS33 [get_ports {display_out[3]}]
    23. set_property IOSTANDARD LVCMOS33 [get_ports {display_out[1]}]
    24. set_property IOSTANDARD LVCMOS33 [get_ports {display_out[2]}]
    25. set_property IOSTANDARD LVCMOS33 [get_ports {display_out[0]}]
    26. set_property IOSTANDARD LVCMOS33 [get_ports {display_out[10]}]

    1. set_property -dict{PACKAGE_PIN R2 IOSTANDARD LVCMOS33}[get_ports s]
    2. set_property -dict{PACKAGE_PIN W5 IOSTANDARD LVCMOS33}[get_ports clk_i]
    3. set_property -dict{PACKAGE_PIN U7 IOSTANDARD LVCMOS33}[get_ports{presentation[0]}]
    4. set_property -dict{PACKAGE_PIN V5 IOSTANDARD LVCMOS33}[get_ports{presentation[1]}]
    5. set_property -dict{PACKAGE_PIN U5 IOSTANDARD LVCMOS33}[get_ports{presentation[2]}]
    6. set_property -dict{PACKAGE_PIN V8 IOSTANDARD LVCMOS33}[get_ports{presentation[3]}]
    7. set_property -dict{PACKAGE_PIN U8 IOSTANDARD LVCMOS33}[get_ports{presentation[4]}]
    8. set_property -dict{PACKAGE_PIN W6 IOSTANDARD LVCMOS33}[get_ports{presentation[5]}]
    9. set_property -dict{PACKAGE_PIN W7 IOSTANDARD LVCMOS33}[get_ports{presentation[6]}]
    10. set_property -dict{PACKAGE_PIN U2 IOSTANDARD LVCMOS33}[get_ports{dn0[0]}]
    11. set_property -dict{PACKAGE_PIN U4 IOSTANDARD LVCMOS33}[get_ports{dn0[1]}]
    12. set_property -dict{PACKAGE_PIN V4 IOSTANDARD LVCMOS33}[get_ports{dn0[2]}]
    13. set_property -dict{PACKAGE_PIN W4 IOSTANDARD LVCMOS33}[get_ports{dn0[3]}]
    14. set_property -dict{PACKAGE_PIN V13 IOSTANDARD LVCMOS33}[get_ports{hour[0]}]
    15. set_property -dict{PACKAGE_PIN V3 IOSTANDARD LVCMOS33}[get_ports{hour[1]}]
    16. set_property -dict{PACKAGE_PIN W3 IOSTANDARD LVCMOS33}[get_ports{hour[2]}]
    17. set_property -dict{PACKAGE_PIN U3 IOSTANDARD LVCMOS33}[get_ports{hour[3]}]
    18. set_property -dict{PACKAGE_PIN P3 IOSTANDARD LVCMOS33}[get_ports{hour[4]}]
    19. set_property -dict{PACKAGE_PIN N3 IOSTANDARD LVCMOS33}[get_ports{hour[5]}]
    20. set_property -dict{PACKAGE_PIN P1 IOSTANDARD LVCMOS33}[get_ports{hour[6]}]
    21. set_property -dict{PACKAGE_PIN L1 IOSTANDARD LVCMOS33}[get_ports{hour[7]}]

  • 相关阅读:
    【二叉树Java】二叉树遍历前序中序后序遍历的非递归写法
    Java面向对象编程
    Swift语言配合HTTP写的一个爬虫程序
    回文 马蹄集
    c# 多线程创建及线程同步
    PassUAC的简单实现(二)
    hive-udf
    广告业务存储神器:华为云GaussDB(for Redis)
    如何删除重复文件?简单操作法方法盘点!
    第五十周总结——JavaScript设计模式
  • 原文地址:https://blog.csdn.net/m0_73553411/article/details/133944531