数字电路基础实验 Verilog代码编写(2)时序逻辑

本文介绍了Verilog语言中时序逻辑部分的关键电路设计,包括R-S触发器、D触发器和JK触发器的工作原理、电路结构以及实例实现。通过这些基本触发器,读者将理解如何构建移位寄存器和环形计数器,实现数据存储和计数功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        完成上篇的组合逻辑电路,将要学习的是Verilog语言中的另一重要部分,时序逻辑部分电路,加入了时钟,能让电路实现更丰富的功能。(代码参考自网上)

1.R-S触发器:

        基本RS触发器可以由两个与非门按正反馈方式闭合构成。通常将Q端的状态定义为锁存器的状态,即Q=1时,称为锁存器处于1的状态;Q=0时,称锁存器处于0的状态,电路具有两个稳态。电路要改变状态必须加入触发信号,因是与非门构成的基本RS触发器,所以,触发信号是低电平有效。非Rd和非Sd是一次信号,只能一个个加,即它们不能同时为低电平,因为会有逻辑矛盾(Q == 非Q)。

 module rs_ff( 
  input wire clk,r,s,			//rs触发器输入信号		
  output reg q,				//输出端口q,在always块里赋值,定义为reg型
  output wire qb				//输出端口非q
 );
 assign qb = ~q;
 always@(posedge clk)
begin
	case({r,s})
		2'b00:  q <= q;      //r,s同时为低电平,触发器保持状态不变
		2'b01:  q <= 1'b1;	   //触发器置1状态
		2'b10:  q <= 1'b0;   //触发器置0状态
		2'b11:  q <= 1'bx;   //r,s同时为高电平有效,逻辑矛盾,触发器为不定态
	endcase
end
endmodule

 

`timescale 1ns/100ps    //仿真时间单位/时间精度
   module rs_ff_tb();       
    reg    clk,r,s;         	//需要产生的激励信号定义
    wire   q,qb;      	  //需要观察的输出信号定义
    //初始化过程块
    initial
    begin
	  clk = 0;
	  r = 0;
	  s = 0;
	  #50
	  r = 0;
	       s = 1;
	  #50
	  r = 1;
          s = 0;
	  #50
	  r = 1;
	       s = 1;
	  #50
	  r = 0;
	       s = 1;
    end
   always #10 clk = ~clk;      //产生输入clk,频率50MHz
   //module调用例化格式
   rs_ff  u1 (      //rs_ff表示所要例化的module名称,u1是我们定义的例化名称
		.clk(clk),     //输入输出信号连接。
		.r(r),
		.s(s),
		.q(q),    //输出信号连接
		.qb(qb)   
             );
  endmodule
 

2.D触发器:

       从D触发器的特性我们知道,它的状态仅仅取决于时钟信号达到之前瞬间的D信号。为了防止SR锁存器的S、R被同时置1的情况,常采用维持阻塞结构的D触发器,其电路结构如下,边沿触发器的次态仅仅取决于CLK信号上升沿(或下降沿)到达时刻输入信号的状态。

  module dff
   (						//模块名及参数定义
    input clk,rst,d,	
    output reg q,
    output wire qb
   );
   assign qb = ~q;
   always @( posedge clk )   //只有clk上升沿时刻触发
	if(!rst)				  //复位信号判断,低有效
		q <= 1'b0;        //复位有效时清零
	else
		q <= d;           //触发时输出q值为输入d
  endmodule

 

  `timescale 1ns/100ps    //仿真时间单位/时间精度
  module dff_tb();       
   reg    clk,rst,d;         	//需要产生的激励信号定义
   wire   q,qb;      	  //需要观察的输出信号定义 
   //初始化过程块
   initial
   begin
	 clk = 0;
	 rst = 0;
	 d = 0;
	 #50
	 rst = 1;
   end
   always #10 clk = ~clk;      //产生输入clk,频率50MHz
   always #15 d = ~d;
   //module调用例化格式
   dff  u1 (      //dff表示所要例化的module名称,u1是我们定义的例化名称
		.clk(clk),     //输入输出信号连接。
		.rst(rst),
		.d(d),
		.q(q),    //输出信号连接
		.qb(qb)   
           );
  endmodule

3.JK触发器:

        带使能端RS锁存器的输入端R=S=1时,锁存器的次态不确定,这一因素限制了其应用。为了解决这个问题,根据双稳态元件两个输出端互补的特点,用Q和非Q反馈控制输入信号,并用J代替S,用K代替R,构成了J-K锁存器。

module jk_ff
(						//模块名及参数定义
input clk,j,k,rst,set,	
output reg q,
output wire qb
);
 
assign qb = ~q;
//clk上升沿以及复位和置位下降沿时触发器工作
always@(posedge clk or negedge rst or negedge set)
	begin
		if(!rst)
			q <= 1'b0;			// 异步清零
		else if (!set)
			q <= 1'b1;  		// 异步置1
		else
			case({j,k})
				2'b00:		q <= q;		//保持
				2'b01:		q <= 0;		//置0
				2'b10:		q <= 1;		//置1
				2'b11:		q <= ~q;	//翻转
			endcase
	end
endmodule

 

`timescale 1ns/100ps    //仿真时间单位/时间精度
 module jk_ff_tb();       
 reg    clk,j,k,rst,set;         	//需要产生的激励信号定义
wire   q,qb;      	  //需要观察的输出信号定义
 
//初始化过程块
initial
begin
	clk = 0;
	j = 0;
	k = 0;
	rst = 1;
	set = 1;
	#50
	set = 0;
	#50
	set = 1;
	#50
	rst = 0;
	#50
	rst = 1;
end
always #10 clk = ~clk;      //产生输入clk,频率50MHz
always #20 j = ~j;
always #30 k = ~k;
//module调用例化格式
jk_ff  u1 (      //jk_ff表示所要例化的module名称,u1是我们定义的例化名称
		.clk(clk),     //输入输出信号连接。
		.j(j),
		.k(k),
		.rst(rst),
		.set(set),
		.q(q),    //输出信号连接
		.qb(qb)   
);
endmodule

4.移位寄存器:

        如果将多个触发器级联就构成一个多位的移位寄存器,如下图所示,是以4位移位寄存器为例的逻辑电路图,其中的LD/SHIFT是一个置数/移位控制信号。当LD/SHIFT为1时,在CP作用下,从输入端A、B、C、D并行接收数据;当LD/SHIFT为0时,在CP作用下,将寄存器中的数据顺序移出,空位由输入端SIN补充。这种寄存器常用来进行并行数据到串行数据的转换。

 

module shift7
(
input wire clk,           //输入时钟
input wire rst,			  //复位信号
input wire [6:0] datain,  //并行输入数据
output wire  dataout 	  //串行输出数据
);
 
reg [6:0] data;
 
always @(posedge clk)
	if(!rst)
		data <= datain;			//同步复位,复位时并行数据存入变量data
	else
		begin
			data[6] <= 1'b0;		//最高为补0
			data[5] <= data[6];
			data[4] <= data[5];
			data[3] <= data[4];
			data[2] <= data[3];
			data[1] <= data[2];
			data[0] <= data[1];     //右移一位
		end
 
assign dataout = data[0];		//串行输出
 
endmodule

`timescale 1ns/100ps    //仿真时间单位/时间精度
module shift7_tb;	
reg clk, rst;       //需要产生的激励信号定义
reg [6:0]datain;    
wire dataout;       //需要观察的输出信号定义
initial
	begin
		clk =0;
		rst =1;
		datain =7'b1110101;   //所需移位数据
		#50
		rst =0;
		#100
		rst =1;
	end
always #20 clk =~clk;     //产生时钟信号 频率25MHz
//module调用例化格式
shift7 u1 (
				.clk	(clk),
				.rst	(rst),
				.datain	(datain),
				.dataout(dataout)
			);
endmodule

 5.环形计数器:

       将移位寄存器的输出q0连接到触发器q3的输入,并且在这4个触发器中只有一个输出为1,另外3个为0,这样就构成了一个环形计数器。初始化复位时,给q0一个置位信号,则唯一的1将在环形计数器中循环移位,每4个时钟同期输出一个高电平脉冲。

 

module ring #
(
parameter  CNT_SIZE = 8
)
(
input wire clk,rst,           //时钟和复位输入
output reg [CNT_SIZE-1:0] cnt    	  //计数器输出
);
always@(posedge clk)
	if(!rst)
		cnt <= 8'b0000_0001;        //复位初值
	else
		cnt <= {cnt[0],cnt[CNT_SIZE-1:1]};  //右移循环计数
endmodule
 

 

`timescale 1ns/100ps    //仿真时间单位/时间精度
module ring_tb;	
reg clk,rst;
wire [7:0]	q;
initial
	begin
		clk =0;
		rst =0;
		#20
		rst =1;
	end	
always#10 clk =~clk;
ring u1 (
				.clk	(clk),
				.rst	(rst),
				.cnt	(q)
				);
endmodule

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值