串行移位寄存器原理详解
板上集成的用的是 三线数码管
HC595 串行移位寄存器。
D触发器也可以作为开关来使用。前三个时钟周期保持不变,到第四个才发送过去,latch信号用来控制输出到引脚上面。使用3根信号线,完成了四位数据的输出。
通过移位寄存器和输出锁存器实现 是要驱动开发板上的8位数码管
FPGA 三个输入端口,控制8位输出。74HC595 可以级联,FPGA需要通过74HC595这个芯片把16位的数据(sel+seg)把16位信号传递到端口来驱动数码管。
FPGA工作的时候是50Mhz,二分频变成了 25Mhz,
串行移位寄存器驱动数码管显示设计与实现
hex_sel 为位选,hex为段选信号。
对于74HC595芯片,该芯片在SH_CP的上升沿将DS(DIO)上的数据移入内部的寄存器
目的:因此我们需要保证DS上的数据在SH_CP上升沿前后的一段时间,保持稳定 手段:FPGA要在SH_CP的下降沿改变DS的值。
先移入的数据,在高位输出。
SHCP = 12.5MHZ
- 使用一个计数器计数分频得到12.5M的信号
- SH_CP 不要想成一个时钟信号,而是当成一个普通信号,一个和DS、ST_CP一样的普通信号
新建一个文件: HC595_driver.v
`timescale 1ns/1ns
module HC595_driver(
clk,
reset,
data,
s_en,
shcp,
stcp,
ds
);
input clk;
input reset;
input [15:0] data;
input s_en;
output reg shcp;
ouput reg stcp;
output reg ds;
parameter cnt_max = 2;
reg [15:0] r_data;
always@(posedge clk)
if(s_en)
r_data <= data;
reg [7:0] div_cnt;
always@(posedge clk or negedge reset)
if(!reset)
div_cnt <= 0;
else if(div_cnt == cnt_max - 1)
div_cnt <= 0;
else
div_cnt <= div_cnt + 1'b1;
wire sck_plus;
assign sck_plus = (div_cnt == cnt_max - 1);
reg [5:0] shcp_edge_cnt;
always@(posedge clk or negedge reset)
if(!reset)
shcp_edge_cnt<= 0;
else if(sck_plus) begin
if(shcp_edge_cnt == 6'd33)
shcp_edge_cnt <= 0;
else
shcp_edge_cnt <= shcp_edge_cnt +1'b1;
end
always@(posedge clk or negedge reset)
if(!reset) begin
case(shcp_edge_cnt)
0: begin
sh_cp <= 0;
st_cp <= 1'd0;
ds <= r_data [15];
end
1: sh_cp <= 1;
2: begin
sh_cp <= 0;
ds <= r_data [14];
end
3:sh_cp <= 1'd1;
...
31: sh_cp <= 1'd1;
32: st_cp <= 1'd1;
default:
begin
sh_tp <= 0;
st_cp <= 0;
ds <= 0;
end
endcase
end
endmodule
testbench.v
`timescale 1ns/1ps
module HC595_driver_tb;
reg clk;
reg reset;
reg [15:0] data;
reg s_en;
wire sh_cp;
wire st_cp;
wire ds;
HS595_driver HC595_driver(
clk,
reset,
data,
s_en,
sh_cp,
ds
);
initial clk = 1;
always #10 clk = ~clk;
initial begin
reset = 0;
data = 0;
s_en = 0;
#201;
reset = 1;
#500;
data = 16'h47a9;
s_en = 1;
#20;
s_en = 0;
#2000;
data = 16'h5832;
s_en = 1;
#20;
s_en = 0;
#2000;
$stop;
end
endmodule
仿真发现DS有一段红色的信号;
|