220 likes | 505 Views
FPGA 和 SOPC 应用 —— 同步设计、状态机. 华中科技大学启明学院电工电子科技创新中心 王贞炎. 内容. 一些基本概念 同步设计 同步的概念 同步设计原则 建立和保持时间 时钟使能 数据有效标志(数据使能) 流水线 跨时钟域问题 有限状态机 概念 状态编码 设计步骤和方法. 一些基本概念. 面积和速度 面积:是指一个设计所消 耗 的 FPGA 资源的量, 可理解为一个设计在 FPGA 中占用的“面积”。主要由 LE 衡量,还包括 RAM 和 DSP 块等。 速度:是指一个设计在 FPGA 芯片上能稳定运行的最高频率。
E N D
FPGA和SOPC应用——同步设计、状态机 华中科技大学启明学院电工电子科技创新中心 王贞炎
内容 • 一些基本概念 • 同步设计 • 同步的概念 • 同步设计原则 • 建立和保持时间 • 时钟使能 • 数据有效标志(数据使能) • 流水线 • 跨时钟域问题 • 有限状态机 • 概念 • 状态编码 • 设计步骤和方法
一些基本概念 • 面积和速度 • 面积:是指一个设计所消耗的FPGA资源的量,可理解为一个设计在FPGA中占用的“面积”。主要由LE衡量,还包括RAM和DSP块等。 • 速度:是指一个设计在FPGA芯片上能稳定运行的最高频率。 • “面积”和“速度”是一对对立统一的矛盾体。可以用更多的逻辑资源实现更快速的处理,也可以牺牲速度用较少的逻辑资源——“面积”和“速度”互换。科学的设计目标是:在满足设计时序要求的前提下,占用最小的芯片面积;或者在所规定的面积下,使设计的时序余量更大,频率更高。
一些基本概念 • Verilog描述的逻辑的并行性 • Verilog很多语法规则和C语言相似,但两者有本质区别! • 在编写Verilog代码时,要始终记住:“我在描述一个硬件电路的连接,而不是顺序执行的代码。”,对于一个硬件电路,在Verilog描述中各部分语句的“执行”是并发的。 • 一个HDL代码优劣的最终评价标准是其描述实现的硬件电路的性能(包括面积和速度两个方面),而不能只是片面地追求代码的简洁。 • 在编写Verilog代码前,应先对系统要实现的硬件电路的功能原理和结构连接有一个明确地规划。硬件描述语言是描述硬件的,要首先对硬件实现“胸有成竹”,才能描述得好。
一些基本概念 • 合理分配模块 • 在设计一个较大的系统时,往往需要将系统分为多个模块。模块的划分是需要合理考虑的。 • 按实际功能划分模块。 • 划分出来的模块的端口意义尽量简明。 • 一个模块自成一体,调用模块者绝对不需要知道模块内部原理,绝对不需要干涉内部工作过程。 • 模块规模合理。
一些基本概念 • 合理利用资源 • 在设计一个系统时,要了解,什么样的功能适合用LE实现,什么样的功能适合由DSP、CPU实现(包括FPGA内部的DSP、CPU)。实时性要求高、频率高、大量并行的功能模块适合使用传统的FPGA逻辑实现。 • 在做FPGA应用设计时,要对的FPGA芯片全局有宏观上的合理安排,比如时钟、模块组织结构、RAM的利用、面积和速度等问题。 • 善于利用片内RAM、乘法器。
同步设计 • 同步的概念 • 异步数字电路: • 电路的核心逻辑用组合电路实现; • 电路的主要信号并不依赖某个特定的时钟钟信号; • 容易产生毛刺,出现竞争冒险; • 不利于器件移植、不利于时序分析与验证。 • 同步数字电路: • 电路核心逻辑用各种触发器实现; • 电路的主要信号都是由某个特定时钟驱动产生的; • 可以很好地避免毛刺; • 有利于器件移植和时序分析及验证。 • 可编程器件成本越来越低,综合效果越来越强,现代PLD设计首选同步时序设计方式!
同步设计 • 同步设计原则 • 所有信号均由时钟驱动,并且在同一个设计内,尽量让所有数据由同一个时钟驱动 在同步设计中,一切逻辑均可简化为由下面的结构罗列而成:
同步设计 • 触发器的建立和保持时间 • 建立时间(TSU):在时钟有效沿之前数据必须保持稳定的最小时间 • 保持时间(TH):在时钟有效沿之后数据必须保持稳定的最小时间 • 建立时间和保持时间形成一个时间窗,在此窗之内,数据必须保持稳定。 • 同步设计的速度限制,根本上源于建立时间和保持时间的要求 • 建立时间和保持时间是时序分析的基础
同步设计 • 时钟使能 • 在同一个设计中,尽量让所有的模块使用同一时钟,让所有的“always@(xxxedge clk)”中的clk是同一个clk。 • 系统中不同部分的信号速率可能不一样,使用时钟使能控制处理速率。
同步设计 • 数据有效标志(数据使能) • 对于对单个数据进行处理需要数个、甚至不确定数目的时钟周期的模块,可为数据输入和输出端口配备数据使能信号,用于与前后级模块交互 • Clk:工作时钟 • ARst:异步复位 • DataIn:数据输入 • DataEn:输入数据有效 • DataOut:数据输出 • DataValid:输出数据有效指示 • 每一级的DataValid接至后级的DataEn • DataEn有效时,采入数据进行处理 • 处理完数据输出的同时让DataValid有效,通知下级
同步设计 • 流水线 • 流水线处理是高速设计中的常用设计手段 • 时序逻辑处理数据流就是天然的流水线结构
同步设计 • 跨时钟域问题 • 有时候不可避免会出现连续两个数据处理模块需要使用不同的时钟,前级的数据由一个时钟驱动输出,而后级的输入却由另一个时钟采入 • 跨时钟域数据同步也是FPGA设计的一个较常见问题,处理不好会影响系统稳定 • 跨时钟域的形式: • 同频异相问题,两个时钟域频率相同,但相差不固定 • 异频问题,两个时钟域的频率不同
同步设计 • 跨时钟域问题 • 一般同步方法: • 两级寄存器采样,即用后级时钟对前级数据采样两次。这种做法可以有效地减少亚稳态的传播,使后级电平都是有效电平值,但偶尔也会出现错误数据。该方法适用于对错误不敏感的同频异相时钟域数据的同步。 • 使用DCFIFO,可以可靠解决异步时钟域数据的同步问题,注意数据满和空
同步设计 • 跨时钟域问题 • 特殊情况——转换低频时钟为时钟使能:: • 如果低频时钟频率远低于高频时钟(两倍以上),建议用高频时钟将低频时钟的跳沿同步为单周期使能信号。 • 典型例子:用外部处理器与FPGA逻辑交互。外部处理器送来的时钟可能很慢。 module edge2en(input clk, input edge, output en); reg curr, last; assign en = ~last & curr; always@(posedge clk) begin curr <= in; last <= curr; end endmodule
有限状态机 • 概念 • 状态机是复杂逻辑功能(如算法机中的流程控制器)实现的最主要也是最有效的手段 • 状态机记录自身工作状态,通过输入与当前状态来确定下个状态,并通过当前状态和输入来确定输出
有限状态机 • 状态编码 • 二进制编码或格雷码 • 独热码 • 独热码是一次只有一位为高的编码 • CPLD中一般使用格雷码 • FPGA中一般使用独热码 • 综合工具一般会自动把已识别的状态机中的编码转换为独热码
有限状态机 • 设计步骤 • 1、逻辑抽象,绘制状态转换图 • 2、状态化简与分配 • 3、总结状态驱动和输出 • 4、编写代码 • 设计方法 • 三段式状态机代码编写 • 状态转移段(时序逻辑) • 状态驱动段(组合逻辑) • 输出段(一般为组合逻辑)
有限状态机 • 实例:序列检测器 • 检测到输入序列110,则输出1,否则0 • 状态转换图: (S0:输入一个0;S1:收到一个1;S2:连续收到两个1;S3:连续收到110)
有限状态机 • 实例:序列检测器 • // 状态驱动 • always @(*) begin • case(state) • s0: next_state=((seq==1)?s1:s0); • s1: next_state=((seq==1)?s2:s0); • s2: next_state=((seq==1)?s2:s3); • s3: next_state=((seq==1)?s1:s0); • default: next_state=((seq==1)?s1:s0); • endcase • end • // 输出 • always @(*) begin • case(state) • s0: det=1'b0; • s1: det=1'b0; • s2: det=1'b0; • s3: det=1'b1; • default: det=1'b0; • endcase • end • endmodule module seqdet ( input clk, input rst, input seq, output reg det ); localparam s0=4'h1; localparam s1=4'h2; localparam s2=4'h4; localparam s3=4‘h8; // 独热码 reg [3:0] state, next_state; // 状态转移 always@(posedge clk) begin if(rst) state <= s0; else state <= next_state; end
有限状态机 • 实例:序列检测器 module testbench; reg clk; reg rst; reg [19:0]data = 20'b0011_1001_0101_1011_0000; wire out; reg [4:0] cnt; wire seq = data[cnt]; integer i; initial begin clk = 1'b0; cnt = 5'b0; rst = 1'b1; #40 rst = 1'b0; end always begin #10 clk = ~clk; end always@(posedge clk) begin if(cnt < 5'd19) cnt <= cnt + 1'b1; else $stop(); end seqdet seqdet_inst(.clk(clk), .rst(rst), .seq(data[cnt]), .det(out)); endmodule
课后作业题 • 采用有限状态机(要求“三段式”)的方法设计一个姓名拼音序列检测器,包含端口: • Clock 一位输入 主时钟 • ARst 一位输入 异步复位,到有效 • SeqIn 八位输入 序列输入 • Detected 一位输出 序列有效 • 各人检测自己的姓名 • 姓名拼音采用姓全拼、名缩写的方式,如“王贞炎”缩写为“WangZY”,大小写区分。 • 在Verilog代码和仿真中,采用ASCII码表示字母。 • 自行编写testbench并在ModelSim中仿真,testbench中必须包含: • 两个连续完整的姓名序列,如“WangZYWangZY” • 一个有头无尾的不完整序列,如“WangZ” • 一个无头有尾的不完整序列,如“ngZY” • 在检测到完整序列后,从Detected输出一个宽度为一个时钟周期的高电平。