74HC595芯片
图1 功能框图
图2 芯片引脚图
图3 引脚功能图
引脚定义:
SHCP |
Input |
移位寄存器时钟 |
STCP |
Input |
存储寄存器使能 |
MR_n |
Input |
复位信号,低电平有效 |
DS |
Input |
输入串行信号 |
Q[7:0] |
Output |
输出并行信号 |
Q7S |
Output |
输出串行信号 |
图4 时序图
时序图说明:
1. 蓝色虚线表示SHCP的时钟上升沿,橙色信号表示当前DS信号在移位寄存器中的时序,Qn表示DS信号在STCP上升沿进入到锁存器的时序。
2. 当前DS信号经过移位8次,在第7时钟周期上升沿后到达Q7S,之后在STCP上升沿可将串行输入的8位信号锁存到锁存器中,再同步输出到Q0-Q7。
3. 图中Q0-Q7的信号变化是同一位DS信号,在不同时钟周期下时在锁存器中的位置;正常使用时要等串行输入信号全部输入后再对STCP拉高,可将串行数据同步转换为并行数据。
4. Q7S是将串行输入的信号移位8次后再串行输出,逻辑上Q7S的值等于移位寄存器最高位的值(在功能框图中可以看出)。
5. DS信号在SHCP下降沿变化,在SHCP上升沿稳定用来移位,移位寄存器中的数据在STCP下降沿变化(即在SHCP上升沿进行移位操作),在STCP上升沿稳定用来转入锁存器中。
根据功能框图coding
module serial_to_parallel
(
input shcp ,
input stcp ,
input mr_n ,
input ds ,
output reg[7:0]Q ,
output reg Q7s
);
reg [7:0] m_data ; //8位移位寄存器
always@(posedge shcp or negedge mr_n)
begin
if(!mr_n)
m_data <= 8'd0;
else
begin
m_data[0] <= ds;
Q7s <= m_data[7]; // 串行输出,根据图1得出,Q7s连接在第八位移位寄存器之后,相较于原串行信号延后8个shcp周期; 该语句也是并行信号转串行信号的关键
//m_data <= (m_data << 1);
m_data[7:1]<= m_data[6:0] ;
end
end
always@(posedge stcp)
begin
Q <= m_data; //省略锁存器,直接赋值给Q
end
endmodule
Tb:
`timescale 1ns/1ns
`define clk_period 20
module tb();
reg shcp;
reg stcp;
reg mr_n;
reg ds ;
wire [7:0] Q;
wire Q7s;
initial
begin
shcp <= 1'd0;
stcp <= 1'd0;
mr_n <= 1'd0;
ds <= 1'd0;
#(`clk_period)
mr_n <= 1'd1;
ds <= 1'b1; //8'b1110_0001
#(`clk_period)
ds <= 1'b1;
#(`clk_period)
ds <= 1'b1;
#(`clk_period)
ds <= 1'b0;
#(`clk_period)
ds <= 1'b0;
#(`clk_period)
ds <= 1'b0;
#(`clk_period)
ds <= 1'b0;
#(`clk_period)
ds <= 1'b1;
#(`clk_period)
stcp <= 1'b1;
#(`clk_period*10)
$stop;
end
always@(*) #(`clk_period/2) shcp <= ~shcp;
serial_to_parallel
u1
(
.shcp(shcp),
.stcp(stcp),
.mr_n(mr_n),
.ds (ds ),
.Q (Q ),
.Q7s (Q7s )
);
endmodule
仿真结果如下
图5 modelsim仿真波形图
注意:
移位操作
m_data[0] <= ds;
m_data <= m_data << 1;
上述移位语句在仿真中的现象是:只进行移位,不会对0位更新;原因是:Verilog标准定义了在同一个always块中,可对某同一变量进行多次非阻塞赋值,但在多次赋值中,只有最后一次赋值对该变量起作用。
阻塞赋值与非阻塞赋值的区别/理解:
阻塞赋值时,不允许任何别的Verilog语句的干扰,直到现行的赋值完成时刻,即把RHS赋值给LHS的时刻,才允许别的赋值语句的执行。可以理解为阻塞赋值的执行只有一个步骤的操作,即计算RHS并更新LHS。
非阻塞赋值的操作过程可以看成两个步骤,①在赋值开始时刻,计算非阻塞赋值RHS表达式,②在赋值结束时刻,更新非阻塞赋值LHS表达式。在两个步骤期间,其他的Verilog语句包括其他的非阻塞赋值语句都能同时计算RHS和更新LHS。
移位寄存器的正确写法:
第一种:m_data[7:1] <= m_data[6:0];左移,右移同理
第二种:dout <= {din[6:0],din[7]};循环左移,不循环时{ din[6:0],0}
74HC595驱动模块(并转串)
根据图4设计驱动模块
引脚定义:
CLK |
Input |
系统时钟,50MHz |
RST_N |
Input |
复位信号,低电平有效 |
DATA[15:0] |
Input |
数码管的段选和位选信号,由模块内部产生; |
SHCP |
Output |
移位寄存器时钟 |
STCP |
Output |
存储寄存器标志位 |
DS |
Output |
74hc595芯片的输入串行信号 |
module hc595_driver(
input clk ,
input rst_n ,
input [15:0] data ,
output reg shcp ,
output reg stcp ,
output reg ds
);
reg [1:0] cnt ;
reg shcp_dge;
reg [4:0] cnt_dge ;
/*---------divider 6.25M-----------*/
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cnt <= 1'd0;
shcp_dge <= 1'd0;
end
else if(cnt == 2'd3)
begin
cnt <= 1'd0;
shcp_dge <= 1'd1;
end
else
begin
cnt <= cnt + 1'd1;
shcp_dge <= 0;
end
end
always@(posedge clk or negedge rst_n) //shcp变化沿计数,上升沿时ds值稳定用来移位,下降沿时ds值变化
begin
if(!rst_n)
cnt_dge <= 5'd0;
else if(shcp_dge)
begin
if(cnt_dge == 5'd31)
cnt_dge <= 5'd0;
else
cnt_dge <= cnt_dge + 1'd1;
end
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
shcp <= 1'd0;
stcp <= 1'd0;
ds <= 1'd0;
end
else if(shcp_dge)
case(cnt_dge) //根据图4时序写出,
0: begin shcp <= 1'd0; stcp <= 1'd1; ds <= data[15];end
1: begin shcp <= 1'd1; end
2: begin shcp <= 1'd0; stcp <= 1'd0; ds <= data[14];end
3: begin shcp <= 1'd1; end
4: begin shcp <= 1'd0; ds <= data[13];end
5: begin shcp <= 1'd1; end
6: begin shcp <= 1'd0; ds <= data[12];end
7: begin shcp <= 1'd1; end
8: begin shcp <= 1'd0; ds <= data[11];end
9: begin shcp <= 1'd1; end
10: begin shcp <= 1'd0; ds <= data[10];end
11: begin shcp <= 1'd1; end
12: begin shcp <= 1'd0; ds <= data[9];end
13: begin shcp <= 1'd1; end
14: begin shcp <= 1'd0; ds <= data[8];end
15: begin shcp <= 1'd1; end
16: begin shcp <= 1'd0; ds <= data[7];end
17: begin shcp <= 1'd1; end
18: begin shcp <= 1'd0; ds <= data[6];end
19: begin shcp <= 1'd1; end
20: begin shcp <= 1'd0; ds <= data[5];end
21: begin shcp <= 1'd1; end
22: begin shcp <= 1'd0; ds <= data[4];end
23: begin shcp <= 1'd1; end
24: begin shcp <= 1'd0; ds <= data[3];end
25: begin shcp <= 1'd1; end
26: begin shcp <= 1'd0; ds <= data[2];end
27: begin shcp <= 1'd1; end
28: begin shcp <= 1'd0; ds <= data[1];end
29: begin shcp <= 1'd1; end
30: begin shcp <= 1'd0; ds <= data[0];end
31: begin shcp <= 1'd1; end
endcase
end
endmodule
仿真图,与时序图4结果一致文章来源:https://www.toymoban.com/news/detail-413624.html
参考:https://www.bilibili.com/video/BV1KE411h7AZ?p=12&vd_source=3e7443822a1d6c6318a816938f700f14文章来源地址https://www.toymoban.com/news/detail-413624.html
到了这里,关于FPGA学习笔记(6)——串、并转换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!