IC面试知识点之Verilog设计部分

本文详细介绍了Verilog在数字系统设计中的应用,特别是分频器的实现,包括偶数分频和奇数分频的逻辑设计。此外,还讲解了序列检查器的两种实现方式——有限状态机和移位寄存器。内容涵盖了状态机的编写方法、同步和异步FIFO的设计,并讨论了格雷码、BCD码和onehot码的作用。同时,文章还探讨了触发器与锁存器的区别,竞争冒险的解决方法,以及低功耗设计的策略。
摘要由CSDN通过智能技术生成

1. 设计分频器
   在数字系统的设计中经常会碰到需要使用多个时钟的情况。时钟信号的产生通常具有两种方法,一种是使用PLL(Phase Locked Loop,锁相环),可生成倍频、分频信号;
   另一种则是使用硬件描述语言构建一个分频电路。
   (1) 偶数分频
       方法:假设为N分频,只需设计一个计数器从0计数到 N/2-1(一共N/2个基准时钟),然后将输出分频时钟翻转、计数器清零,如此循环就可以得到 N分频。
       比如要实现4分频,那么使用一个计数器,在计数到1的时候已经过了两个基本时钟的上升沿,此时翻转时钟,最终出来的就是4分频的时钟。
       // 使用两个always模块,一直用来控制计数的循环(计数到N/2-1),一个用来产生分频的信号,这种是等占空比的实现方法
       module devive_6(
            input  wire clk, res,
            output reg  out
        );
            reg[1:0] count = 2'b00;
            always@(posedge clk or negedge res) begin
                if (!res) count <= 2b`0;
                else if(count == 2b`10) count <= 2b`0;
                else count <= count + 1;
            end
            always @(posedge clk or posedge res) begin
                if (!res) out <= 0;
                else if (count == 2b`10) out <= ~out;
                else out <= out;
            end
        endmodule
        // 若想要实现的是非等占空比的,可以使用标志位的方法
        module device_6_flag(
            input wire clk,
            input wire rst,
            output reg flag_clk
        );
            reg[2:0] count = 3b`0;
            always @(posedge clk or posedge rst) begin
                if (!rst) begin
                    // reset
                    count <= 1b`0;
                    flag_clk <= 0;
                end
                // 计数器在0~5之间循环计数
                else if (count == 3d`5) count <= 3b`0;
                // 当计数到4时,flag_clk跳转到1,这样每个时钟间隔6个clk
                // 这里计数到其他数值也有同样的效果,只不过这个通常用来设置计数标志位,
                // 应该在计数最大值CNT_MAX-1时将标志位置置1,因为如果根据标志位的高电平来控制输出时,要在下一个时钟到来时才能
                else if (count == 3b`4) flag_clk <= 1;
                else begin
                    count <= count + 1b`1;
                    flag_clk <= 0;
                end
            end
        endmodule
   (2) 奇数分频
       分频信号是基准时钟信号周期的3倍,那么3分频时钟信号的边沿变化肯定发生在第1.5个时钟周期(第2个时钟周期的下降沿),
       同理5分频的边沿变化肯定发生在第2.5个时钟周期(第3个时钟周期的下降沿),同理7分频的边沿变化肯定发生在第3.5个时钟周期(第4个时钟周期的下降沿)。
       同时我们会发现既然边沿的变化都发生在0.5个时钟周期,那么肯定要利用到时钟的下降沿。
       方法:
       第一个always模块控制计数器的循环,计数到N-1,对上升沿敏感;
       第二个always模块产生对基准时钟上升沿敏感的时钟,每当计数到(N-1)/2-1时,时钟翻转;计数到计数器最大值时再翻转
       第三个always模块产生对基准时钟下降沿敏感的信号,每当计数到(N-1)/2-1时,时钟翻转;计数到计数器最大值时再翻转
       将 上升沿敏感的信号和 下降沿敏感的信号相与(&&)即N分频电路
       module divider_n(
            input wire clk,
            input wire rst,
            output reg out
        );
            parameter CNT_MAX = 5;
            reg[CNT_MAX-1:0] count;
            reg clk1, clk2;

            // 第一个always模块控制count的计数
            always@(posedge clk or negedge rst) begin
                if (!rst) count <= 8d`0;
                else if(count == CNT_MAX - 1) count <= 8d`0;
                else count <= count + 1;
            end

            // 第二个always模块控制clk1的分频,高电平3个时间周期,低电平2个时间周期
            always @(posedge clk or negedge rst) begin
                if (!rst) clk1 <= 0;
                else if (count == (CNT_MAX - 1)/2) clk1 <= 0;
                else if (count == CNT_MAX - 1) clk1 <= 1;
            end

            // 第三个always模块控制clk2的分频,高电平3个时间周期,低电平2个时间周期
            always @(negedge clk or negedge rst) begin
                if (!rst) clk2 <= 0;
                else if (c

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值