• 【题目精刷】2023禾赛-FPGA


    为了能够在做题目的过程中学习到需要的知识,对每道题知识参考或者知识详情都做了详细的说明。方便后续复习。欢迎对文中的解答批评指正。

    题目评价

    • 难易程度:★★☆☆☆
    • 知识覆盖:★☆☆☆☆
    • 超纲范围:☆☆☆☆☆
    • 值得一刷:★☆☆☆☆

    不值得一刷。

    1. 使用最少的电路实现二分频,给出原理图。


    在这里插入图片描述


    2. 解释环形振荡器的构成和原理


    环形振荡器的构成:
    奇数个反相器首尾连接而成。

    环形振荡器的原理:
    利用门电路的固有传输延迟。电路没有稳态,静态下(假定没有振荡时)任何一个反相器的输入和输出都不可能稳定在高电平或低电平,只能处于高低电平之间,处于放大状态。

    在这里插入图片描述

    在这里插入图片描述


    3. 什么是建立时间和保持时间?


    建立时间:有效时钟沿到来之前数据必须保持稳定的时间。
    保持时间:有效时钟沿到来之后数据必须保持稳定的时间。


    4. 建立时间和保持时间哪个和时钟速率有关?列出建立时间和保持时间违例的情况。


    建立关系:与工作频率有关
    t l a u n c h + t c l k 2 q + t l o g i c + t s e t u p < t c a p t u r e + t c y c l e t_{launch} + t_{clk2q} + t_{logic} + t_{setup}< t_{capture} + t_{cycle} tlaunch+tclk2q+tlogic+tsetup<tcapture+tcycle

    保持关系:
    t l a u n c h + t c l k 2 q + t l o g i c < t c a p t u r e + t h o l d t_{launch} + t_{clk2q} + t_{logic} < t_{capture} + t_{hold} tlaunch+tclk2q+tlogic<tcapture+thold

    题目问法有点问题,理论上建立时间和保持时间都是时序器件固有属性,与时钟频率都无关,应该是想问建立关系和保持关系哪个和时钟速率有关。

    建立时间违例的情况:从建立关系就可以推断

    • 组合逻辑过于复杂,时延较大。
    • 负时钟偏斜较大。
    • 时钟频率过大。时序关系太严格。
    • 工艺库较落后。

    保持时间违例的情况:

    • 正时间偏斜较大。
    • 工艺库较落后。

    5. 详细给出建立时间和保持时间裕量的计算方法

    在这里插入图片描述


    对于max延迟分析(setup/recovery):
    - 裕量 = 数据需要的时间 - 数据到达的时间
    对于min延迟分析(hold/removal):
    - 裕量 = 数据到达的时间 - 数据需要的时间

    建立时间裕量:
    ( t c a p t u r e + t c y c l e − t s e t u p ) − ( t l a u n c h + t c l k 2 q + t l o g i c ) (t_{capture} + t_{cycle} - t_{setup}) - (t_{launch} + t_{clk2q} + t_{logic} ) (tcapture+tcycletsetup)(tlaunch+tclk2q+tlogic)

    保持时间裕量:
    ( t c a p t u r e + t h o l d ) − ( t l a u n c h + t c l k 2 q + t l o g i c ) (t_{capture} + t_{hold}) - (t_{launch} + t_{clk2q} + t_{logic}) (tcapture+thold)(tlaunch+tclk2q+tlogic)


    6. 介绍FPGA SLICEL 的基本构成单元。


    参考:可配置逻辑块(configurable logic block,CLB)资源学习

    SLiceL的基本构成单元:

    • LUT6*4:每个LUT有六个独立的输入(A1-A6),两个独立的输出(O5-O6)。一个SLice中的四个LUT分别以A B C D编号。
    • 多路选择器*3: 用于查找表的尾款拓展
    • 进位链*1:时间超前进位逻辑。
    • 触发器*8:每个slice有8个存储单元。四个可以配置为边沿触发D型触发器或电平敏感的锁存器。

    7. 不需要流水线。给出两种8bit a/b 的实现方法。


    参考:除法器的实现(恢复余数、不恢复余数、级数展开、Newton-Raphson)


    8. 介绍同步复位和异步复位的优缺点,写出异步复位同步释放的代码。


    复位类型优点缺点
    同步复位①抗干扰性能强,可以剔除复位信号中周期短于时钟周期的毛刺。①占用更多的逻辑资源。
    ②有利于STA工具分析。②对复位信号脉宽有要求,必须大于时钟周期,很难保证复位信号到达各寄存器的时序。
    ③有利于基于周期的仿真工具的仿真。③复位信号依赖于时钟,如果电路时钟出现问题无法复位。
    异步复位①无需额外逻辑资源,实现简单。可保证复位引脚到个寄存器始终偏斜最小。①复位信号易受外界干扰,对毛刺敏感。
    ②复位信号不依赖于时钟。②复位信号释放的随机性,产生时序违例导致电路处于亚稳态。

    异步复位同步释放的代码:

    reg R_rstn;
    reg R1_rstn;
    
    always @(posedge clk or negedge rstn)
    begin
        if(~rstn)
        begin
            R_rstn <= 1'b0;
            R1_rstn <= 1'b0;
        end
        else   
        begin
            R_rstn <= 1'b1;
            R1_rstn <= R_rstn;
        end
    end
    
    always @(posedge clk or negedge R1_rstn)
    begin
        if(~R1_rstn)
        begin
            // 用户逻辑 
        end
        else  
        begin 
            // 用户逻辑 
        end
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    9. 分析如下电路可能产生的问题,解决?

    在这里插入图片描述


    类似多bit数据跨时钟域问题,可能会导致亚稳态或数据无法正确跨时钟域。
    不能直接采样,需要加入对于处理电路,首先将多bit信号组合逻辑输出在CLK_a寄存一拍,然后进行单bit跨时钟域处理。
    在这里插入图片描述

    如果CLK_a比CLK_b慢,可以采用打两拍的方法。
    如果CLK_a比CLK_b快,可以采用脉冲同步器或者握手处理。


    10.统计1024个连续 8bit 输入数据的直方图,实时输出当前出现次数最多的数字。


    题目没有限制要用尽量少的逻辑资源,简单的写法可以generate 256 个寄存器,来一个对应数据就加一,这样在实现上是比较简单的。如果考虑到综合实现,用一个ram来存比较合适。

    实时输出当前出现次数最多的数字?这个有点复杂,意味着要持续完成256个出现次数的比较,并且还要得到最大次数对应的地址。

    每帧数据输出最大值还差不多?T_T

    这里只实现了直方图统计,比较简单

    实现RTL:

    `timescale 1ns/1ps  
    
    module histogram(
        input       clk   ,
        input       rstn  ,
        input       en_i  ,
        input [7:0] data_i
    );
    //--- internal signal definitions ---
    //=== parameter definitions ===			
                                    
    //=== reg definitions ===  
    reg            en_r     ;
    reg  [7:0]     data_r	;  	
    reg            en_r1     ;
    reg  [7:0]     data_r1	; 		
    reg            wr_en_r  ;
    reg  [7:0]     wr_addr_r;
    reg  [9:0]     wr_din_r ;    
    reg            rd_en_r  ;
    reg  [7:0]     rd_addr_r; 
    
    
    //=== wire definitions === 				
    wire  [9:0]    rd_dout_w;                                      
                                        
    //--- Main body of code ---
    always @(posedge clk or negedge rstn)
    begin
        if(~rstn) 
        begin
            en_r   <= 1'd0;
            data_r <= 8'd0;
            en_r   <= 1'd0;
            data_r <= 8'd0;
        end 
        else
        begin
            en_r   <= en_i  ;
            data_r <= data_i;
            en_r1   <= en_r  ;
            data_r1 <= data_r;
        end
    end
    
    always @(posedge clk or negedge rstn)
    begin
        if(~rstn) 
        begin
            rd_en_r   <= 1'b0;
            rd_addr_r <= 8'b0;
        end 
        else
        begin
            rd_en_r   <= en_i;
            rd_addr_r <= data_i;
        end
    end
    
    always @(posedge clk or negedge rstn)
    begin
        if(~rstn) 
        begin
            wr_en_r   <= 1'b0;
            wr_addr_r <= 8'b0;
            wr_din_r  <= 10'b0;
        end 
        else
        begin
            wr_en_r   <= en_r1;
            wr_addr_r <= data_r1;
            wr_din_r  <= rd_dout_w + 1'b1;
        end
    end
    
    dpram dpram_u(
        .clk    (clk      ),
        .rstn   (rstn     ),
        .wr_en  (wr_en_r  ),
        .wr_addr(wr_addr_r),
        .wr_din (wr_din_r ),
        .rd_en  (rd_en_r  ),
        .rd_addr(rd_addr_r),
        .rd_dout(rd_dout_w)
    );
    
    
    endmodule 
    
    //只是模拟RAM,代码不可综合。
    module dpram(
        input            clk,
        input            rstn,
        input            wr_en,
        input  [7:0]     wr_addr,
        input  [9:0]     wr_din,
        input            rd_en,
        input  [7:0]     rd_addr,
        output reg [9:0] rd_dout
    );
    
    reg [9:0] mem [0:255] ;
    
    always @(posedge clk)
    begin
        if (wr_en)
        begin
            mem[wr_addr] <= wr_din;
        end
    end
    
    always @(posedge clk)
    begin
        if (rd_en)
        begin
            rd_dout <= mem[rd_addr];
        end
    end
    
    always @(negedge rstn) begin
        if (~rstn)
        begin
            data_rst();
        end
    end
    
    task data_rst();
    begin:data_rst
        integer i;
        for (i = 0; i < 256; i = i + 1) begin
            mem[i] = 0;
        end
    end
    endtask  
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136

    testbench:

    `timescale 1ns/1ps   
    
    module histogram_tb ();
    
    parameter T = 10;
    
    reg       clk   ;
    reg       rstn  ;
    reg       en_i  ;
    reg [7:0] data_i;
    
    
    initial begin
        clk    = 'd1;
        rstn   = 'd0;
        en_i   = 'd0;
        data_i = 'd0;
        #(T*10) 
        rstn   = 'd1;
        #(T*5)
        data_gen();
        $finish();
    end
    always #(T/2) clk <= ~clk;
    
    task data_gen();
    begin:data_gen
        integer i;
        for (i = 0; i < 1024; i = i + 1) begin
            @(negedge clk);
            en_i   <= 'd1;
            data_i <= {$random} % 256;
        end
        @(posedge clk);
        en_i   <= 'd0;
    end
    endtask
    
    histogram histogram_u(
        .clk   (clk   ),
        .rstn  (rstn  ),
        .en_i  (en_i  ),
        .data_i(data_i)
    );
    
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    Modelsim脚本:

    vlib work  
    vlog histogram.v  histogram_tb.v 
    vsim -novopt work.histogram_tb 
    
    
    • 1
    • 2
    • 3
    • 4

    Revision

    时间说明
    20220622初始版本
  • 相关阅读:
    vue elementui 实现从excel从复制多行多列后粘贴到前端界面el-table
    SpringBoot整理-Actuator
    http协议详解01——http协议概念及工作流程
    设计模式学习笔记(一)
    Android工程接入UnityLibrary工程
    RK3568开发笔记-SATA接口调试
    格利尔在北交所上市:市值突破9亿元,朱从利夫妇为实控人
    温度响应性纳米水凝胶光子品体/纤维素修饰荧光水凝胶/载脂质体水凝胶的制备方法
    Ubuntu 20.04使用源码安装nginx 1.14.0
    每个开发人员都想使用的编程语言
  • 原文地址:https://blog.csdn.net/lum250/article/details/125407004