赞
踩
目录
四个D触发器,连接同一个Clk,每个时钟上升沿,数据向右移一位,如果想实现四个数据全移位结束后一起输出的话,则需要将输出Q连接4个D触发器输出,这四个D触发器的时钟LATCH时钟信号与之前的四个D触发器的时钟Clk上升沿不是同时出现,所以就可以实现串转并输出。
同理,如果想实现8位数据的传输,则需要8+8=16个D触发器进行实现串并转换
74HC595 是用于 CMOS 应用的 HC 系列逻辑器件中的一部分。74HC595 器件包含对8位 D 类存储寄存器进行馈送的 8位串行输入/并行输出移位寄存器。
移位寄存器时钟(SRCLK)和存储寄存器时钟(RCLK) 均为正边沿触发。如果将两个时钟连接在一起,则移位寄存器始终比存储寄存器早一个时钟脉冲。
ZYNQ702数码管只有三个管脚,其上集成移位寄存器——74HC595芯片(8个D触发器、8个输出锁存器实现8位数据串转并)。FPGA输出16位数据(16进制),2个HC595级联,16个时钟周期后实现串转并
SRCLK:移位时钟信号SRCLK;DOI:输入信号DOI;RCLK:锁存时钟信号RCLK
SRCLK高电平,信号进入D触发器Q端,RCLK高电平,信号进入相应锁存器Q端,此时Q0~Q7才有输出.
级联:DIO数据进入第一级芯片,8个时钟周期后,进入下一级芯片
从功能表中可以看出当移位时钟信号SRCLK上升沿到来时有效,即将数据存入D触发器中;对于锁存时钟信号RCLK来说,当其上升沿到来时,移位寄存器的值存入到存储寄存器之中。
从下图中可以看出74HC595的时序要求为:1.当供电电压为2V时,其SRCLK时钟频率最大值为5MHZ,当供电电压为4.5V时,其SRCLK时钟频率最大值为25MHZ,本实验开发板供电电压为3.3V文中并没有提到3。3V,所以有两种办法:第一种是选取最低的5MHZ肯定是没有问题的;第二种方法是用中间值12.5MHZ进行实现。综合起来看第二种方法更好一点。2.RCLK高脉冲时间至少要为SRCLK高脉冲时间的一半。3. 2V时SRCLK上升沿到来之前的125ns,DIO数据线数值不可以变化。4. 2V时SRCLK上升沿比RCLK上升沿先到来至少94ns
首先输入16位的数值,其中8位SEL信号,8位SEG信号,然后输出三条线作为驱动74HC595的输入线。
实现逻辑仿真框图如下:图中可见最小时间单元为40ns。
上一章节写过的代码
- module hex8(
- input Clk,
- input Reset_n,
- input [31:0]Disp_Data,
- output reg [7:0]SEL,
- output reg [7:0]SEG
- );
-
- reg [29:0]cnt_1ms;
- reg Flag_1ms; //每1毫秒切换一个数码管
- reg [2:0]cnt_sel;//位选信号
- parameter MCNT = 50000-1;
-
- //定时一毫秒
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- cnt_1ms <= 0;
- else if(cnt_1ms == MCNT)
- cnt_1ms <= 0;
- else
- cnt_1ms <= cnt_1ms + 1;
-
- //产生一个一毫秒到来的高脉冲信号
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- Flag_1ms <= 0;
- else if(cnt_1ms == MCNT)
- Flag_1ms <= 1;
- else
- Flag_1ms <= 0;
-
- //cnt_sel自加逻辑实现(每1毫秒自加一次切换一个数码管)
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- cnt_sel <= 0;
- else if(Flag_1ms)
- cnt_sel <= cnt_sel + 1;
- else
- cnt_sel <= cnt_sel;
-
- //数码管的位选择逻辑
- always@(posedge Clk)begin
- case(cnt_sel)
- 0: SEL <= 8'b0000_0001;
- 1: SEL <= 8'b0000_0010;
- 2: SEL <= 8'b0000_0100;
- 3: SEL <= 8'b0000_1000;
- 4: SEL <= 8'b0001_0000;
- 5: SEL <= 8'b0010_0000;
- 6: SEL <= 8'b0100_0000;
- 7: SEL <= 8'b1000_0000;
- default:SEL <= 8'b0000_0000;
- endcase
- end
-
- reg [3:0]data_temp;//显示16种数值8 + 4 + 2 + 1 = 15,
- //查找表中列出SEG段选信号的各种情况。
- always@(posedge Clk)begin
- case(data_temp)
- 0: SEG <= 8'b1100_0000; //0
- 1: SEG <= 8'b1111_1001; //1
- 2: SEG <= 8'b1010_0100; //2
- 3: SEG <= 8'b1011_0000; //3
- 4: SEG <= 8'b1001_1001; //4
- 5: SEG <= 8'b1001_0010; //5
- 6: SEG <= 8'b1000_0010; //6
- 7: SEG <= 8'b1111_1000; //7
- 8: SEG <= 8'b1000_0000; //8
- 9: SEG <= 8'b1001_0000; //9
- 10: SEG <= 8'b1000_1000;//A
- 11: SEG <= 8'b1000_0011;//B
- 12: SEG <= 8'b1100_0110;//C
- 13: SEG <= 8'b1010_0001;//D
- 14: SEG <= 8'b1000_0110;//E
- 15: SEG <= 8'b1000_1110;//F
- default:SEL <= 8'b1111_1111;//全灭
- endcase
- end
-
- //8路选择器实现逻辑
- always@(*)
- case(cnt_sel)
- 0:data_temp <= Disp_Data[3:0];
- 1:data_temp <= Disp_Data[7:4];
- 2:data_temp <= Disp_Data[11:8];
- 3:data_temp <= Disp_Data[15:12];
- 4:data_temp <= Disp_Data[19:16];
- 5:data_temp <= Disp_Data[23:20];
- 6:data_temp <= Disp_Data[27:24];
- 7:data_temp <= Disp_Data[31:28];
- default:data_temp = 4'b0000;
- endcase
-
- endmodule
代码中可以看出使用的频率是12.5MHZ,所以SCLK的周期是80ns。
- `timescale 1ns / 1ps
-
- module HC595_Driver(
- input Clk,
- input Reset_n,
- input [7:0]SEL,
- input [7:0]SEG,
- output reg DIO,
- output reg SCLK,
- output reg RCLK
- );
-
- parameter MCNT = 2-1;
-
- reg [29:0]Cnt_40ns;
- reg [4:0]Bit_cnt;
-
- //40ns定时单位
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- Cnt_40ns <= 0;
- else if(Cnt_40ns == MCNT)
- Cnt_40ns <= 0;
- else
- Cnt_40ns <= Cnt_40ns+1;
-
- //位控制逻辑
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- Bit_cnt <= 0;
- else if(Cnt_40ns == MCNT)
- Bit_cnt <= Bit_cnt + 1;
- else
- Bit_cnt <= Bit_cnt;
-
- //不同时刻做不同的事情(线性序列机,找到最小时间单位40ns)
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)begin
- DIO <= 1'd0;
- RCLK <= 1'd0;
- SCLK <= 1'd0;
- end
- else begin
- case(Bit_cnt)
- 0: begin DIO <= SEG[7]; SCLK <= 1'd0;RCLK <= 1'd1;end//高位先给
- 1: begin SCLK <= 1; RCLK <= 1'd0;end
- 2: begin DIO <= SEG[6]; SCLK <= 1'd0;end
- 3: begin SCLK <= 1; end
- 4: begin DIO <= SEG[5]; SCLK <= 1'd0;end
- 5: begin SCLK <= 1; end
- 6: begin DIO <= SEG[4]; SCLK <= 1'd0;end
- 7: begin SCLK <= 1; end
- 8: begin DIO <= SEG[3]; SCLK <= 1'd0;end
- 9: begin SCLK <= 1; end
- 10: begin DIO <= SEG[2]; SCLK <= 1'd0;end
- 11: begin SCLK <= 1; end
- 12: begin DIO <= SEG[1]; SCLK <= 1'd0;end
- 13: begin SCLK <= 1; end
- 14: begin DIO <= SEG[0]; SCLK <= 1'd0;end
- 15: begin SCLK <= 1; end
- 16: begin DIO <= SEL[7]; SCLK <= 1'd0;end
- 17: begin SCLK <= 1; end
- 18: begin DIO <= SEL[6]; SCLK <= 1'd0;end
- 19: begin SCLK <= 1; end
- 20: begin DIO <= SEL[5]; SCLK <= 1'd0;end
- 21: begin SCLK <= 1; end
- 22: begin DIO <= SEL[4]; SCLK <= 1'd0;end
- 23: begin SCLK <= 1; end
- 24: begin DIO <= SEL[3]; SCLK <= 1'd0;end
- 25: begin SCLK <= 1; end
- 26: begin DIO <= SEL[2]; SCLK <= 1'd0;end
- 27: begin SCLK <= 1; end
- 28: begin DIO <= SEL[1]; SCLK <= 1'd0;end
- 29: begin SCLK <= 1; end
- 30: begin DIO <= SEL[0]; SCLK <= 1'd0;end
- 31: begin SCLK <= 1; end
- endcase
- end
- endmodule
- `timescale 1ns / 1ps
-
- module HC595_Driver_tb();
-
- reg Clk;
- reg Reset_n;
- reg [7:0]SEL;
- reg [7:0]SEG;
- wire DIO;
- wire SCLK;
- wire RCLK;
-
- HC595_Driver HC595_Driver(
- .Clk(Clk),
- .Reset_n(Reset_n),
- .SEL(SEL),
- .SEG(SEG),
- .DIO(DIO),
- .SCLK(SCLK),
- .RCLK(RCLK)
- );
-
- initial Clk = 1;
- always #10 Clk = ~Clk;
-
- initial
- begin
- Reset_n = 0;
- SEL = 8'b0000_0001;
- SEG = 8'b0101_0101;
- #201;
- Reset_n = 1;
- #5000;
- SEL = 8'b0000_0010;
- SEG = 8'b1010_1010;
- #5000;
- SEL = 8'b1010_0101;
- SEG = 8'b0000_1101;
- #5000;
- $stop;
- end
- endmodule
- `timescale 1ns / 1ps
-
- module hex8_hc595_test(
- input Clk,
- input Reset_n,
- //input SW,
- output DIO,
- output SCLK,
- output RCLK
- );
-
- wire [7:0]SEL;//hex8模块与HC595_Driver模块连接到了一起。用导线wirej进行连接.
- wire [7:0]SEG;
- wire [31:0]Disp_Data;
-
- hex8 hex8(
- .Clk(Clk),
- .Reset_n(Reset_n),
- .Disp_Data(Disp_Data),
- .SEL(SEL),
- .SEG(SEG)
- );
-
- HC595_Driver HC595_Driver(
- .Clk(Clk),
- .Reset_n(Reset_n),
- .SEL(SEL),
- .SEG(SEG),
- .DIO(DIO),//底层模块的输出端口不能用reg型了
- .SCLK(SCLK),//底层模块的输出端口不能用reg型了
- .RCLK(RCLK)//底层模块的输出端口不能用reg型了
- );
-
- assign Disp_Data = 32'h01221843;
- // always@(*)
- // case(SW)
- // 0: Disp_Data <= 32'h01221843;
- // 1: Disp_Data <= 32'h12345678;
- // endcase
-
- endmodule
这就实现了数码管动态显示的功能了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。