锁存器
②其次,当门控锁存器的控制信号有效时,锁存器就变成了一个组合电路,时序逻辑电路的模型就等效为两个各组合电路互为反馈的反馈系统,因此,系统有可能会因为瞬态特性不稳定而产生振荡现象。
触发器分为两种,一种是主从触发器和边沿触发器。主从触发器在时钟有效期内(主触 发器)接收数据,在时钟边沿输出状态转换。 边沿触发器在时钟边沿期间, 触发器才接收数 据并使输出状态转换。 目前,主从触发器基本上已经很少见了,实际使用的大都是边沿触发器。
从寄存数据的角度来讲,寄存器和锁存器的功能是相同的;它们的区别在于寄存器是同 步时钟控制,而锁存器是电位信号控制。 一般的设计规则是:在绝大多数设计中避免产生锁存器。它会让您设计的时序完蛋,并 且它的隐蔽性很强,非老手不能查出。
锁存器具备下列特点:
(1)对毛刺敏感(使能信号有效时,输出状态可能随输入多次变化,产生空翻,对下一级电路很危险),不能异步复位,因此在上电后处于不确定的 状态。
(2)锁存器会使静态时序分析变得非常复杂,不具备可重用性。 (首先, 锁存器没有时 钟参与信号传递,无法做 STA;其次,综合工具会将 latch 优化掉,造成前后仿真结果不一 致)
(3)在FPGA中基本的单元是由查找表和触发器组成的,若生成锁存器反而需要 更多的资源。根据锁存器的特点可以看出,在电路设计中,要对锁存器特别谨慎,如果设计 经过综合后产生出和设计意图不一致的锁存器,则将导致设计错误,包括仿真和综合。因此, 在设计中需要避免产生意想不到的锁存器。 如果组合逻辑的语句完全不使用 always 语句块,就可以保证综合器不会综合出锁存器。
input [3:0] data,
input [1:0] enable ,
else if(enable==1) q = data[2];
// else if(enable==2) q = data[1];
// else if(enable==3) q = data[0];
(4)其他的情况(摘自他人博客,我均用DC综合过,结果正确)
case1(有锁存器):
module mux_latch
(
input [3:0] data,
input [1:0] valid,
input flag,
output reg valid_data
);
always @ (*)
begin
if(valid==2'd0) valid_data = data[3];
if(valid==2'd1) valid_data = data[2];
if(valid==2'd2) valid_data = data[1];
if(valid==2'd3) valid_data = data[0];
end
endmodule
//---------------------------------------------------------
case 2解决办法1:加else与if配对
always @ (*)
begin
if(valid==2'd0) valid_data = data[3];else
if(valid==2'd1) valid_data = data[2];else
if(valid==2'd2) valid_data = data[1];else
if(valid==2'd3) valid_data = data[0];else
valid_data = 1'b0;
end
//-----------------------------------------------------------
case3解决办法2:赋初始值
always @ (*)
begin
valid_data = 1'b0
if(valid==2'd0) valid_data = data[3];
if(valid==2'd1) valid_data = data[2];
if(valid==2'd2) valid_data = data[1];
if(valid==2'd3) valid_data = data[0];
end
//----------------------------------------------------------
case 4(有锁存器)
always @ (*)
begin
case(valid)
2'b00 : begin if(flag) valid_data = data[0];end
2'b01 : begin if(flag) valid_data = data[1];end
2'b10 : begin if(flag) valid_data = data[2];end
2'b11 : begin if(flag) valid_data = data[3];end
endcase
//-------------------------------------------------------------
case 5(有锁存器)
always @ (*)
begin
case(valid)
2'b00 : begin if(flag) valid_data = data[0];end
2'b01 : begin if(flag) valid_data = data[1];end
2'b10 : begin if(flag) valid_data = data[2];end
2'b11 : begin if(flag) valid_data = data[3];end
default:valid_data=1'b0;
endcase
end
//--------------------------------------------------------------
case 6解决办法---赋初始值
always @ (*)
begin
valid_data=1'b0;
case(valid)
2'b00 : begin if(flag) valid_data = data[0];end
2'b01 : begin if(flag) valid_data = data[1];end
2'b10 : begin if(flag) valid_data = data[2];end
2'b11 : begin if(flag) valid_data = data[3];end
endcase
end
//----------------------------------------------------------------
case7解决办法-- 加else
always @ (*)
begin
case(valid)
2'b00 : begin if(flag) valid_data = data[0];else valid_data = 1'b0;end
2'b01 : begin if(flag) valid_data = data[1];else valid_data = 1'b0;end
2'b10 : begin if(flag) valid_data = data[2];else valid_data = 1'b0;end
2'b11 : begin if(flag) valid_data = data[3];else valid_data = 1'b0;end
endcase
end