当前位置: 首页 > article >正文

【IC每日一题】

IC每日一题

  • 1:锁存器(latch)、触发器(flip-flop)、寄存器的概念及区别
    • 1.1 概念
    • 1.2 锁存器的危害
    • 1.3 如何避免产生锁存器
  • 2 手撕题:边沿检测
    • 2.1 边沿检测(上升沿、下降沿、双边沿)
      • 2.1.1 波形图
      • 2.1.2 算法步骤
      • 2.1.3 代码
    • 2.2 序列模三检测器
      • 2.2.1 描述
      • 2.2.2 波形图
      • 2.2.3 代码

本文主要介绍:锁存器/寄存器概念以及锁存器的危害和避免方法、边沿检测和序列模三检测;

1:锁存器(latch)、触发器(flip-flop)、寄存器的概念及区别

1.1 概念

锁存器latch:锁存器是电平出发的存储单元,数据存储的动作(状态转换)取决于输入(或使能)的信号的电平值,仅当锁存器处于使能状态时,输出才会随着数据输入发生变化;
常见的锁存器包括三个端口:数据输入口、数据输出口、使能端。当使能端为高电平时,输入口的数据直接送到输出口,此时输入输出口可以看成是直接连通的;当使能端为低电平时,输出口的数据保持之前的数据不变,无论输入口的数据怎么变化,输出都保持不变,就是把原来的状态锁存下来了(所以才叫锁存器)。
触发器(flip-flop):触发器是边沿敏感的存储单元,数据存储的动作(状态转换)只在时钟的上升沿或下降沿的到来发生;
锁存器和触发器是底层具体的物理单元

寄存器(register):是用于暂时存放参与运算的数据和运算结果值。具体来说:在实际的数字系统中,通常把能够用来存储一组二进制代码的同步时序逻辑电路称为寄存器。寄存器常用触发器来构建;一个触发器能够存储一位二进制码,因此N个触发器的时钟端口连接起来能构成存储N位二进制的寄存器;

从寄存功能角度看:寄存器和锁存器的功能是相同的;

锁存器和寄存器区别:锁存器是电平触发,而触发器(寄存器)是clk边沿触发。锁存器在不锁存数据时,输出随输入变化;但一旦数据锁存时,输入对输出不产生任何影响。在设计中,基本是要绝对的避免综合产生锁存器

1.2 锁存器的危害

1.对毛刺敏感:使能信号有效时,输出状态随输入多次变化,容易产生空翻,不能异步复位;在上电后处于不确定状态;
2.STA静态时序分析复杂:锁存器没有时钟参与,无法做STA,综合工具会将latch优化掉,造成前仿后仿结果不一致,因此静态时序分析困难;
3.资源消耗:在FPGA中,由于FPGA是由查找表和触发器组成的,生成锁存器需要消耗更多资源;但是在IC中,若是锁存器和寄存器都是由与非门搭建的话,锁存器消耗资源更少;在ASIC设计中,除了CPU(高速电路)或者RAM(面积敏感)这类电路,一般绝不提倡使用锁存器;

1.3 如何避免产生锁存器

1.组合逻辑:若是组合逻辑,组合逻辑的语句完全不适用always语句块,就可以保证综合器不会综合出锁存器;
2.基于always语句块(类wire型和真reg型):信号必须要求是reg型,但是综合后是否是reg型还是latch型,是不一定的;
不可简单看if-else,缺少else; case-default,缺少default;
在这里插入图片描述

Vivado综合电路
在这里插入图片描述

修改如下,避免产生latch:
在这里插入图片描述

可以把右边形式的称为"类wire"形;类wire型
–类wire型:要想避免产生latch,就一定要避免“自己等于自己”这种情况;
–真reg型:即使if没有else,case没有default,也是不会产生latch;在else缺失的情况下,寄存器的值保持不变,相当于缺省"q<=q",reg是不怕自己等于自己的;
所以下面这种情况也会产生latch;

always @(*) begin
	if(~enable) begin
		out1 = 1'b0;
	end else begin
        out1 = out1;
    end
end

总结:无论是真reg型还是wire型,都心里有意识:if-else,case-default都要写全,这也是一个良好的代码意识,但同时也意识到当review别人代码时,缺省也是对的
组合逻辑中,不完整的 if - else 结构及case-default,会产生 latch

2 手撕题:边沿检测

2.1 边沿检测(上升沿、下降沿、双边沿)

2.1.1 波形图

在这里插入图片描述

2.1.2 算法步骤

边沿检测的核心思想是“打拍子+逻辑运算”;
上升沿检测:din & ~din_r
下降沿检测:din_r & ~din;
双边沿检测:上面两个做或运算;

2.1.3 代码

//=======================================
//--Author  : colonel
//--Date    :11—29
//--Module  : edge_check
//--Function: check a edge including: posedge,negedge,both clk
//=======================================
module edge_check (
//==========================< 端口 >=========================
    input wire clk,
    input wire rst_n,
    input wire din,

    output wire edge_pos,
    output wire edge_neg,
    output wire edge_both
);
//==========================< 信号 >=========================
reg     din_r;

//=========================================================
//-- din_r: flip_flop
//=========================================================
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        din_r <= 1'b0;
    end else begin
        din_r <= din;
    end
end

//=========================================================
//-- edge_pos,edge_neg,edge_both
//=========================================================
assign edge_pos = din & ~din_r;
assign edge_neg = ~din & din_r;
assign edge_both= edge_pos | edge_neg;

endmodule

2.2 序列模三检测器

2.2.1 描述

描述:输入口是1bit,每次进来一位数据,检查当前序列是否能整除3,能则输出1,否则输出0.
例如:
序列=1,out=0;
序列=11,out=1;
序列=110,out=1;
序列=1101,out=0;
输入表:
在这里插入图片描述

2.2.2 波形图

在这里插入图片描述

2.2.3 代码

//=======================================
//--Author  : colonel
//--Date    :11—29
//--Module  : sequence_modulo3_detector
//--Function: Detect if the input signal sequence din is a multiple of 3
//=======================================
module seq_mod3_detec(
//==========================< 端口 >=========================
    input wire clk,
    input wire rst_n,
    input wire din_vld,
    input wire din,

    output wire detect
);
//==========================< 参数 >=========================
localparam IDLE = 3'b000;
localparam S0 = 3'b001;
localparam S1 = 3'b010;
localparam S2 = 3'b100;

//==========================< 信号 >=========================
reg[4-1:0] sta_cur;
reg[4-1:0] sta_nxt;

//=========================================================
//-- FSM-1: state transiate
//=========================================================
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        sta_cur <= IDLE;
    end else begin
        sta_cur <= sta_nxt;
    end
end

//=========================================================
//-- FSM-2: state jump condition
//=========================================================
always @(*) begin
    case (sta_cur)
        IDLE: begin 
            if(!din_vld) begin
                sta_nxt = IDLE;
            end else begin
                if(din) begin
                    sta_nxt = S0;
                end else begin
                    sta_nxt = S1;
                end
            end
        end
        S0: begin
            if(!din_vld) begin
                sta_nxt = S0;
            end else begin
                if (din) begin
                    sta_nxt = S1;
                end else begin
                    sta_nxt = S0;
                end
            end
        end
        S1 : begin
            if(!din_vld) begin
                sta_nxt = S1;
            end else begin
                if(din) begin
                    sta_nxt = S0;
                end else begin
                    sta_nxt = S2;
                end
            end
        end
        S2: begin
            if(!din_vld) begin
                sta_nxt = IDLE;
            end else begin
                if(din) begin
                    sta_nxt = S2;
                end else begin
                    sta_nxt = S1;
                end
            end
        end
        default: sta_nxt = IDLE;
    endcase

end

//=========================================================
//-- FSM-3: state action
//=========================================================
reg mod3_res;

always @(posedge clk) begin
    if(!rst_n)begin
        mod3_res <= 1'b0;
    end else begin
        case (sta_cur)
            IDLE: mod3_res <= 1'b0; 
            S0: mod3_res <= 1'b1; 
            S1: mod3_res <= 1'b0; 
            S2: mod3_res <= 1'b0;
            default: mod3_res <= 1'b0;
        endcase
    end
end

//=========================================================
//-- detect
//=========================================================
assign detect = mod3_res;

endmodule

注意:以上代码已经过编译无error,但未经过testcase测试

[ref]
1.https://blog.csdn.net/aa666888io89/article/details/119646663
2.https://www.runoob.com/w3cnote/verilog-latch.html
3.https://blog.csdn.net/qq_42622433/article/details/138186418


http://www.kler.cn/a/371435.html

相关文章:

  • [mysql]相关子查询
  • 平均时间复杂度计算
  • 电源完整性
  • 练习LabVIEW第二十四题
  • Kafka认证时Successfully logged in真的认证成功了?
  • 微信小程序25__实现卡片变换
  • 【架构-36】常见的各类锁的特点
  • C++学习:类和对象(二)
  • [ 问题解决篇 ] 解决远程桌面安全登录框的问题
  • 3个模型的交互式多模型IMM,基于EKF的目标跟踪实例(附MATLAB代码)
  • java web调试时清理当前网址的缓存
  • 3.1.3 虚存页面的映射
  • Java学习笔记(九)
  • 云原生后端:现代应用架构的核心力量
  • JavaWeb——Web入门(2/9)-SpringBootWeb:快速入门(入门程序需求、开发步骤、项目相关文件说明、小结)
  • 【Linux网络编程】 --- Linux权限理解
  • ICM20948 DMP代码详解(106)
  • 四、Hadoop 命令高级用法深度剖析
  • 前端之html(二)加入css开篇(一)
  • LeetCode72:编辑距离
  • javaScript中复制一个数组的浅拷贝和深拷贝方法
  • Flutter Web部署到子路径的打包指令
  • 单细胞数据分析(四):细胞亚型注释
  • uniapp写抖音小程序阻止右滑返回上一个页面
  • Vue3使用AntV | X6绘制流程图:开箱即用
  • MPSK(BPSK/QPSK/8PSK)调制解调的Matlab仿真全套