• top_down设计的认知


    写在前面的话

    本节呢,梦翼师兄重点和大家谈一下层次化设计方法,我们所谓的层次化设计,实际上就是对一个很大的系统设计进行拆分,直到拆分成很容易实现的最小模块为止。我们都知道,如果我们想要盖一栋大楼,那么首先一定是先设计好工程图纸,然后建筑工人才可以根据设计图纸施工。那么电子系统设计呢?其实也是这样的,在进行具体代码设计之前,我们首先应该认真分析整个的项目需求,在确定项目需求理解无误的情况下,按照电路功能不同,我们可以将整个系统划分成若干个比较大的子模块,然后根据各子模块的功能,进行进一步的细分,直至无法分解。好的层次划分可以有效降低系统开发难度,同时也有利于团队作战,团队中的每个人只需要负责完成自己的那部分模块,最后由顶层设计者进行组装拼接即可完成整体项目的设计。

    层次化设计框图示例

    如上图所示就是一个简易的层次化设计模型,系统顶层模块只是负责连线,将各功能单元正确的组合起来。而各功能单元又由各自对应的若干子模块组成,同一单元的子模块之间有着相应的级联关系。

    层次化设计实例

    大家还记得梦翼师兄给大家分享的流水灯实验吗?在这里,我们回顾一下,我们首先用状态机实现了流水灯的时序,然后由于LED灯切换时间过快,我们无法看到流水的现象,因此我们又采用了两种方式来限制LED切换,第一种:在状态机中嵌入延时计数器 第二种:创建一个时钟分频模块,然后用慢时钟驱动状态机。我们利用以上两种方式最终都实现了流水灯的结果,而且所有的代码修改都是在同一个文件下。那么今天梦翼师兄和大家一起来学一下层次化设计的实现方式。

    系统顶层架构图

    模块功能介绍

    模块名

    功能描述

    Freq

    时钟分频模块,用来分频产生慢时钟

    LED_Driver

    LED驱动,控制LED灯切换

    Led_flow

    系统顶层模块,负责子模块级联

     顶层模块端口介绍

    端口名

    端口说明

    Clk_sys

    系统50MHz时钟输入

    Rst_n

    系统复位

    Pio_led

    LED驱动端口

    4.1.3.4 系统内部连线介绍

    连线名

    连线说明

    Clk_slow

    分频得到的慢时钟信号

    4.1.3.5 代码解释

    LED_Driver 模块代码

    /****************************************************          

    *   Engineer        :   梦翼师兄

    *   QQ               :   761664056

    *   The module function:流水灯驱动模块

    *****************************************************/

    01  module led_learn(

    02                      clk,   //系统时钟输入

    03                      rst_n, //系统复位

    04                      pio_led//LED驱动输出

    05                  );

    06  //系统输入

    07  input clk;   //系统时钟输入

    08  input rst_n; //系统复位

    09  //系统输出

    10  output reg [3:0]pio_led;//LED驱动输出

    11  //中间寄存器定义

    12  reg [1:0]state;//状态寄存器定义

    13      

    14  //LED驱动逻辑

    15  always@(posedge clk or negedge rst_n)

    16      begin

    17          if(!rst_n)

    18              begin

    19                  pio_led<=4'b1111;//LED全部熄灭

    20                  state<=0;//寄存器赋初值

    21              end 

    22          else begin 

    23              case(state)

    24                  0:begin

    25                      pio_led<=4'b0111;//第一个灯点亮

    26                      state<=1;//状态跳转

    27                  end 

    28                  1:begin

    29                      pio_led<=4'b1011;//第二个灯点亮

    30                      state<=2;//状态跳转                 

    31                  end 

    32                  2:begin

    33                      pio_led<=4'b1101;//第三个灯点亮

    34                      state<=3;//状态跳转                 

    35                  end 

    36                  3:begin

    37                      pio_led<=4'b1110;//第四个灯点亮

    38                      state<=0;//状态跳转                 

    39                  end 

    40                  default:state<=0;

    41                  endcase 

    42          end

    43      end 

    44  endmodule 

    本模块代码就是我们之前做过的做基本状态机驱动模块,每来一个驱动时钟上升沿,状态发生一次跳转,LED值随之发生改变。

    Freq 模块代码

    /****************************************************          

    *   Engineer        :   梦翼师兄

    *   QQ               :   761664056

    *   The module function:时钟分频模块

    *****************************************************/

    01  module freq(clk,rst_n,clk_slow);

    02  input clk;//系统50MHz时钟输入

    03  input rst_n;//系统复位

    04

    05  output reg clk_slow;//慢时钟定义

    06

    07  reg [40:0]counter;//计数器定义

    08

    09  //时钟分频电路

    10  always@(posedge clk or negedge rst_n)

    11      begin

    12          if(!rst_n)

    13              begin

    14                  counter<=0;//计数器赋初值

    15                  clk_slow<=0;//慢时钟赋初值

    16              end 

    17          else 

    18              begin

    19                  if(counter<12)

    20                      counter<=counter+1;

    21                  else 

    22                      begin

    23                          counter<=0;

    24                          clk_slow<=~clk_slow;

    25                      end 

    26              end 

    27      end 

    28  endmodule

    该模块的作用就是利用计数器实现分频:统计一定的快时钟个数,然后驱动慢时钟寄存器值发生翻转,输出慢时钟。

    Led_flow模块代码

    /****************************************************          

    *   Engineer        :   梦翼师兄

    *   QQ               :   761664056

    *   The module function:流水灯顶层模块

    *****************************************************/

    01  module Led_flow(clk,rst_n,pio_led);

    02  input clk;//系统50MHz时钟输入

    03  input rst_n;//系统复位

    04

    05  output  [3:0]pio_led;//LED驱动输出

    06

    07  wire clk_slow;//慢时钟定义

    08          

    09  freq freq(

    10      .clk(clk),    //系统时钟输入

    11      .rst_n(rst_n),//系统复位

    12      .clk_slow(clk_slow)//慢时钟输出

    13    );

    14

    15  led_learn led_learn(

    16      .clk(clk_slow),  //驱动时钟输入

    17      .rst_n(rst_n),   //系统复位

    18      .pio_led(pio_led)//LED驱动输出

    19   );

    20      

    21  endmodule 

    该模块为系统顶层模块,负责将分频模块和LED驱动模块进行组装级联。梦翼师兄强烈建议在顶层模块只做模块级联,绝对不要编写任何逻辑。

    仿真代码

    /****************************************************          

    *   Engineer        :   梦翼师兄

    *   QQ               :   761664056

    *   The module function:流水灯测试模块

    *****************************************************/

    01  `timescale 1ns/1ps //时间单位和精度定义

    02  module tb;

    03

    04  //系统输入

    05  reg clk;   //系统时钟输入

    06  reg rst_n; //系统复位

    07  //系统输出

    08  wire [3:0]pio_led;//LED驱动输出

    09  

    10  initial

    11      begin

    12          clk=0;

    13          rst_n=0;

    14          #1000.1 rst_n=1;

    15      end 

    16      

    17      always #10 clk=~clk;//50MHz时钟

    18      

    19  Led_flow Led_flow(

    20          .clk(clk),       //系统时钟输入

    21          .rst_n(rst_n),   //系统复位

    22          .pio_led(pio_led)//LED驱动输出

    23        );

    24  endmodule

    查看仿真波形如下

    如何查看波形呢?既然逻辑是分模块的,那么我们查看波形是否正确也应该是分模块来看的,首先我们查看 freq模块,freq模块的功能就是快时钟产生慢时钟,通过波形我们可以看到clk_slow慢时钟确实产生了,说明该模块功能正确。

    接下来,我们的目标是将慢时钟作为LED驱动模块的时钟源,也就是说LED驱动模块的时钟端口“clk”频率应该和clk_slow一致,查看波形可知,条件符合,说明顶层级联关系正确。

    最后查看流水灯切换,应该发生在每一个驱动时钟上升沿,由波形图可知,逻辑全部正确,设计结束。

    对于层次化设计,我们可以查看RTL级视图(软件操作请查看梦翼师兄视频)

    可以看到,电路生成的RTL级视图和我们所设计的架构图一致,说明系统顶层连接正确。因此通常情况下,如果是进行层次化设计,设计结束以后我们应该首先查看RTL级视图是否正确,只有确保顶层连接正确的情况下我们才进行电路仿真,查看代码时序逻辑是否正确。

  • 相关阅读:
    5分钟带你了解Kafka的技术架构
    聊聊我的知识体系
    你分得清楚Maven的聚合和继承吗?
    为抖音而生的多闪,如何获取抖音的用户数据?
    消息中间件系列第3讲:使用消息队列需要考虑的几个问题
    消息中间件系列第2讲:如何进行消息队列选型?
    消息中间件系列第1讲:为什么要用消息队列?
    JVM规范系列开篇:为什么要读JVM规范?
    安全编码实践之三:身份验证和会话管理防御
    安全编码实践之二:跨站脚本攻击防御
  • 原文地址:https://www.cnblogs.com/mengyi1989/p/11502817.html
Copyright © 2020-2023  润新知