verilog之时序逻辑电路(附代码)

前言

刚学前端设计的时候,听到的就是组合逻辑、时序逻辑,很重要!但是究竟有什么用?到底怎么体现,没有多少老师可以明确指出来,当自己看的东西多了,就可以理解了,甚至可以得出自己的范式。

到目前为止,要想掌握组合逻辑,就请先掌握本文列出的计数器、触发器、锁存器、寄存器分频器等简单的组合逻辑电路。

1.触发器

包括RS触发器、JK触发器、D触发器、T触发器。

2.锁存器和寄存器

锁存器的功能同触发器类似,但也有本质区别:触发器是在有效时钟沿到来时才发生作用,而锁存器是电平敏感的,只要时钟信号有效,锁存器就会起作用

2.1锁存器

2.1.1电平敏感的1位数据锁存器

module latch1(
	clk,
	d,
	q
);
	input clk,d;
	output q;
	
	assign q = clk?d:q;

endmodule

综合的电路图如下:

在这里插入图片描述

2.1.2带有置位功能和复位功能的电平敏感的1位数据锁存器

module latch2(
	clk,load,reset,d,q
);
input clk,load,reset,d;
output q;

assign q = reset?1'b0:(load?1'b1:(clk?d:q));

endmodule
综合得到的电路图如下:

在这里插入图片描述

2.2 寄存器

推荐阅读FPGA应该掌握的小笔记中涉及到的寄存器知识点。

带有清零功能的8位数据寄存器reg_8.v

推荐阅读:异步复位清零的一些常识

module reg_8(
	out,
	in,
	clk,
	clr
);
	output 	[7:0] out;
	input		[7:0]	in;
	input				clk;
	input				clr;
	reg		[7:0]	out;
	
	always@(posedge clk or posedge clr)
	if(clr)		out <= 0;
	else			out <= in;
endmodule
综合得到的电路图如下:

在这里插入图片描述

3.移位寄存器

3.1 8位左移移位寄存器shiftleft_reg.v

module shiftleft_reg(clk,rst,l_in,s,q);
	input clk,rst,l_in,s;
	output 	[7:0]	q;
	reg		[7:0]	q;
	always@(posedge clk)
	begin
		if(rst)
			q <= 8'b0;
		else if(s)
			q <= {q[6:0],l_in};
		else 
			q <= q;
	end

endmodule

3.2 8位右移移位寄存器

module shiftright_reg(clk,rst,r_in,s,q);
	input clk,rst,r_in,s;
	output 	[7:0]	q;
	reg		[7:0]	q;
	always@(posedge clk)
	begin
		if(rst)
			q <= 8'b0;
		else if(s)
			q <= {r_in,q[7:1]};
		else 
			q <= q;
	end

endmodule

4.分频器

5.计数器

6.其他时序逻辑电路

6.1同步器

当一个时序电路的输入由另一个时钟驱动的电路产生或来自一个外部异步电路时,需要用同步器将输入数据与需要的时钟同步。即常用在跨时钟处理!

简单同步器设计代码Synchronizer.v

module Synchronizer(
	clk,
	data,
	syn
);

input 	clk;
input 	data;
output	syn;
reg 		syn;

always@(posedge clk)
	if(data == 0)
		syn <= 0;
	else 
		syn <=1;

endmodule

仿真文件Synchronizer_tb.v

`timescale 1ns/1ns
`define clk_period 20

module Synchronizer_tb;

	reg 	clk;
	reg 	data;
	wire	syn;

	Synchronizer Synchronizer_inst(
		clk,
		data,
		syn
	);

	initial clk = 1;
	always #(`clk_period/2) clk = ~clk;

	initial begin
		data = 1'b0;
		#(`clk_period*2+5);
		data = 1'b1;
		#(`clk_period*2);
		data = 1'b0;
		#(`clk_period*2+6);
		data = 1'b1;
		#8;
		data = 1'b0;
		#16;
		data = 1'b1;
		#(`clk_period);
		data = 1'b0;
		#(`clk_period*2);
		$stop;
	end

endmodule

功能仿真

在这里插入图片描述

6.2边沿检测电路

在这里插入图片描述

设计代码edge_detect.v

module edge_detect(
	clk				,
	rst_n			,
	data			,
	raising_edge	,
	faling_edge		,
	double_edge		
);
	input		clk				;
	input		rst_n			;
	input		data			;
	output		raising_edge	;
	output		faling_edge		;
	output		double_edge		;
	
	reg data_reg0,data_reg1;

	always@(posedge clk or negedge rst_n)
	if(!rst_n)begin
		data_reg0 <= 1'b0;
		data_reg1 <= 1'b0;
	end
	else begin
		data_reg0 <= data;
		data_reg1 <= data_reg0;
	end
	
	assign raising_edge  = ~data_reg1 &&  data_reg0;
	assign faling_edge   =  data_reg1 && ~data_reg0;
	assign double_edge   =  data_reg1  ^  data_reg0;

endmodule

仿真文件edge_detect_tb.v

`timescale 1ns/1ns
`define clk_period 20

module edge_detect_tb;

	reg		clk				;
	reg		rst_n				;
	reg		data				;
	wire		raising_edge	;
	wire		faling_edge		;
	wire		double_edge		;

	edge_detect edge_detect_inst(
		.clk				(clk				),
		.rst_n			(rst_n			),
		.data				(data				),
		.raising_edge	(raising_edge	),
		.faling_edge	(faling_edge	),
		.double_edge	(double_edge	)	
	);

	initial clk = 1;
	always #(`clk_period/2) clk = ~clk;
	
	initial begin
		rst_n = 1'b0;
		#(`clk_period);
		rst_n = 1'b1;
	end
	
	initial begin
		data = 1'b0;
		#(`clk_period+10);
		data = 1'b1;
		#(`clk_period*3);
		data = 1'b0;
		#(`clk_period-5);
		data = 1'b1;
		#(`clk_period*2);
		data = 1'b0;
		#(`clk_period*3);
		$stop;
	end
endmodule

功能仿真

在这里插入图片描述

  • 16
    点赞
  • 119
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰之行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值