FPGA学习笔记(6)——串、并转换

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.bilibili.com/video/BV1KE411h7AZ?p=12&vd_source=3e7443822a1d6c6318a816938f700f14

  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值