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

综合的电路图如下:

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

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

综合得到的电路图如下:

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

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

综合得到的电路图如下:

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

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

功能仿真

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

6.2边沿检测电路

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

设计代码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

功能仿真

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

上一篇:VIVADO 按键消抖


下一篇:Verilog——IP核RAM实验