概念
EDA(电子设计自动化)
借助于计算机和集成电路技术
采用硬件描述语言(HDL)
EDA 软件自动完成编译, 化简, 综合, 优化等工作
将软件描述的功能转译为硬件电路结构
通过可编程逻辑器件 (PLD) 来实现
ASIC(专用集成电路)
狭义 EDA 计数的设计目标
FPGA&CPLD 是实现这一目标的途径的主流器件
SoC(片上系统 / 系统级芯片)
在单个芯片上完成一个电子系统的功能
IP 核(知识产权核)
分类
软 IP(HDL 程序)
固 IP(时序固定)
硬 IP(电路网表文件)
优势: 调用 IP 核能避免重复劳动, 大大减轻工程师的负担, 缩短设计所需周期.
嵌入式系统
定义
以应用为中心
以计算机技术为基础
专用计算机系统
组成
软件
硬件
PLD(可编程逻辑器件)
出场时是一块不具有任何逻辑功能的空白芯片
内部电路结构近乎可变, 对其编程即改变其内部结构的过程
发展
CPLD(复杂可编程逻辑器件)
结构
可编程 I/O 单元
完成不同电气特性下对输入 / 输出信号的驱动与匹配
基本逻辑单元(宏单元)
结构
"与或" 阵列 -- 组合逻辑功能
也称为乘积项
任何组合逻辑电路都可化为 "与 - 或" 表达式
任何组合电路都可用门或门二级电路实现
任何时序电路都可用组合电路加上存储元件 (存储器, 触发器, RAM) 构成
"与或" 阵列每一个交叉点都是一个可编程熔丝, 如果导通就是实现 "与" 逻辑
在 "与" 阵列后还有一个 "或" 阵列, 用以完成最简逻辑表达式中的 "或" 关系
触发器 -- 时序逻辑功能
其中可编程触发器包含时钟, 复位 / 置位配置功能, 用以实现时序逻辑的寄存器或者锁存器等功能
器件规模用 MC 数量表示(器件型号中的数字即表示 MC 数量)
布线池 / 布线矩阵
一般采用集中式布线池结构
布线池是一个开关矩阵, 通过打通节点可以完成不同 MC 的输入与输出项之间的连接
由于布线池结构固定, CPLD 输入到输出管脚的标准延时固定(称 Pin To Pin 延时), 反映了 CPLD 可实现的最高频率(速度等级)
固有延时 & 传输延时
固有延时
也称惯性延时, 是任何电子器件都存在的一种延时特性
主要物理机制是分布电容效应
惯性延时模型中, 器件输出都有一个固有的延时
信号脉宽 (持续时间) 小于器件的固有延时时, 器件将对输入信号不做反应, 即有输入无输出
传输延时
表示输入与输出之间的一种绝对延时关系
不考虑信号持续时间, 仅表示信号传输推迟或延迟了一个时间段, 该时间段即为传输延时
其他辅助功能模块
FPGA(现场可编程门阵列)
可编程输入输出单元(IOB)
芯片与外界电路的接口
完成不同电气特性下对输入 / 输出信号的驱动与匹配需求
可编程逻辑单元
基于 SRAM 工艺的 FPGA, 其可编程逻辑单元几乎都由查找表 (LUT) 和寄存器组成
逻辑函数发生采用 RAM"数据" 朝朝的方式, 并采用多个查找表构成一个查找表阵列的可编程逻辑阵列
基于查找表的可编程逻辑结构
内部结构灵活
可配置为带同步 / 异步复位或置位 / 时钟使能的触发器
也可配置为锁存器
Altera 可编程逻辑单元通常称 LE(由 1 个寄存器 + 1 个 LUT 构成)
嵌入式块 RAM
一般配置储存结构
单端口 RAM
双端口 RAM
先进先出储存器(FIFO)
FPGA 中没有专用的 ROM 硬件资源, 实现 ROM 需对 RAM 赋初值并保持该初值
布线资源
联通 FPGA 内部所有资源
连线的长度和工艺决定着信号在连线上的驱动能力和传输速度
布线资源的优化与使用和设计的实现结果 (包含速度和面积两个方面) 有直接关系
底层嵌入功能单元
指通用程度较高的嵌入式功能模块
内嵌专用硬核
指那些通用性相对较弱的
不是所有 FPGA 器件都包含硬核(Hard Core)
CPLD&FPGA 对比
FPGA
实现复杂设计, 时序约束和仿真非常重要
工艺上: 实现工艺为 SRAM, 也包括 Flash 和 Anti-Fuse 等
结构上: 查找表(LUT)+ 寄存器结构
编程配置: 一般为配置, 多数属于 RAM 型, 掉电后程序丢失
触发器数量: 多
Pin To Pin 延时: 不可预测
规模: 大
逻辑复杂度: 高
成本价格: 高
保密性: 差
互联结构 / 连线资源: 分段式布线结构, 布线资源丰富
适用设计类型: 触发器丰富, 复杂的时序结构
CPLD
实现简单低成本设计
工艺上: 实现工艺多为 E²CMOS, 也包括 E²PROM,Flash,Anti-Fuse 等
结构上: 乘积项结构
编程配置: 一般为编程, 多为 ROM 型, 掉电后程序不丢失
触发器数量: 少
Pin To Pin 延时: 固定
规模: 小
逻辑复杂度: 低
成本价格: 低
保密性: 好
互联结构 / 连线资源: 集总式布线结构, 布线资源相对有限
适用设计类型: 触发器有限, 乘积项丰富的结构, 完成各种算法和组合逻辑
常见大规模可编程逻辑器件的编程工艺
编程和配置的概念
基于电可擦除存储单元的 E²PROM 或 Flash 技术
CPLD 一般使用此技术进行编程
编程后改变电可擦除存储单元
掉电后信息能保存
基于 SRAM 的编程单元
大部分 FPGA 采用这种编程工艺
编程信息保存在 SRAM 中的, SRAM 在掉电后编程信息立即丢失, 在下次上电后, 还需要重新载入编程信息
该类器件的编程一般称为配置
反熔丝结构和 Flash 结构的 FPGA 的下载为编程
对 FPGA 的专用配置 ROM 的下载为编程
PLD&MCU 区别
硬件资源
PLD: 内部电路结构可修改, 硬件结构功能可任意配置
MCU: 硬件结构固定不变
软件开发
PLD: 采用硬件描述语言 VHDL 和 Verilog HDL 描述电路功能
MCU: 根据程序流程图, 采用 C 语言实现, 执行语句指令
执行方式
PLD: 并行计算且不执行代码, 实现电路结构
MCU: 串行执行指令
算法应用
PLD: 无乘法器, 只能进行简单运算
MCU: 能完成各种复杂运算
HDL(硬件描述语言)
用形式化方法描述数字电路, 设计数字逻辑系统
主要目的: 编写设计文件, 建立电子系统行为级的模拟模型
使用 HDL 设计目标的流程
利用计算机对 HDL 建模的数字逻辑进行模拟
利用逻辑综合工具自动生成符合要求, 且在电路结构上可以实现的数字逻辑网表
根据网表和工艺进行版图设计
生成该工艺条件下电路的延时模型
模拟验证无误后用于制造 ASIC 芯片或者写入 CPLD 和 FPGA 器件中
HDL 综合器 & 软件程序编译器区别
软件程序编译器: 将 C 语言或汇编语言等编写的程序, 编译为 0,1 代码流
HDL 综合器将用 HDL 编写的程序代码, 转化为具体的电路网表结构
应用
用 HDL 建立的数字模型 -- 软核
用 HDL 建模和综合后生成的网表 -- 固核
主流 HDL 为 VHDL 和 Verilog HDL
数字系统设计抽象层次
三个域
行为域
物理域
结构域
五个抽象层次
系统级
算法级
寄存器传输级
逻辑级
电路级
Verilog HDL 数字电路设计
Verilog HDL 模块
Verilog HDL 模块 (module) 结构框架
module 模块名 (端口列表) // 端口定义
端口定义 [描述端口] //I/O 说明
内部信号声明 // 信号类型声明
逻辑功能描述 [描述逻辑功能] // 功能描述
endmodule
端口定义格式
module module_name (port_i);
I/O 说明
- input port_a;
- output port_b;
信号类型声明
e.g.:reg [7:0] clk_out;
分类
wire
输入输出信号未指定类型 (缺省) 时默认为 wire 型
可以做任何表达式的输入, assign 和实例元件的输出
变量取值可为 0,1,x,z, 若未连接到驱动源则其值为高阻态 z
输出值紧跟输入值变化, 不可存, 不可停, 必须由驱动源驱动
reg
默认初始值为不定值 x
综合时, 综合器根据情况确定将其映射为寄存器或连线
默认为无符号数, 赋值为负数会得到二进制补码的结果
integer
32 位有符号整型变量
默认初始值位不定值 x
是整数寄存器
最少可容纳一个 32 位的数, 但是做位向量访问是非法的
逻辑功能描述的三种方式
数据流建模
"assign" 语句
e.g."assign y=(~s)|(b&a);"?
连续赋值
被赋值方必为 wire 型
结构化建模
模块级建模(元件例化)
门级建模
e.g."or u1 (y,as,bs);"
开关级建模
行为级建模
"always" 块语句
过程赋值
被赋值方必为 reg 型, 若要对输出端口赋值必须二次定义
敏感信号列表为触发式, 其中任一信号发生变化即启动
e.g.
同步复位 & 异步复位的区别
区别在于是否受时钟信号控制
同步复位: 复位信号只有在时钟信号来临时才有效
异步复位: 只要异步复位信号到来即有效
体现在 "always" 语句的敏感信号列表中
有限状态机 / 时序机
状态数目有限, 可由表示状态的位数确定
采用 n 位二进制编码的时序机的状态最多有 2^n 种状态
同步 (钟控) 有限状态机(FSM): 具有有限个状态且状态转换由时钟驱动
两种基本类型
米利 (Mealy) 机: 下一状态和输出取决于当前状态和当前输入
摩尔 (Moore) 机: 下一状态取决于当前状态和当前输入, 但输出仅取决于当前状态
系统描述与设计
时序图
状态表
状态图
算法状态机 (ASM) 图
FSM 的状态转移图(STG)
以画图的形式考察
有向图
带有标记的节点
必须考虑到从一个节点出发的所有可能的状态转移
三要素
独立状态
转移条件
转移方向
状态机的状态编码
三种编码方式
二进制编码
即顺序编码
使用了最少数量触发器
速度最慢
格雷码
两个相邻码值仅由一个位即可区分
可减少电路中的电噪声
纠错检错效率高
独热码
速度快
使用更多触发器, 但会导致对机器下一状态和输出的更简单译码逻辑
设计简单
对于状态数目大于 32 的状态机建议使用 Gray 编码, 因为它比 One-Hot 编码需要更少的触发器, 而且由于同时变化的位数少, 它要比二进制编码更加可靠
如果一个状态分配没有将所有的码值都覆盖到, 那么将需要用到附加逻辑, 用以检查, 提取并转移到无用状态, 这种附加逻辑将会对实现设计需要的总 (电路) 面积有影响.
设计优化
资源优化
资源共享
先选后乘, 占用资源更少
先乘后选, 资源耗用多
串行化
将原本耗用资源巨大, 单时钟周期内完成的并行执行逻辑分隔开, 提取相同逻辑模块, 时间复用
使用多个时钟周期完成相同工作
代价为工作速度大大降低
速度优化
流水线设计
寄存器配平
关键路径
关键路径是指设计中从输入到输出经过的延时最长的逻辑路径
从输入到输出的延时取决于信号所经过的延时最大 (或称最长) 路径, 而与其他延时小的路径无关
优化关键路径是一种提高设计工作速度的有效方法
EDA 设计流程
EDA 的 FPGA/CPLD 设计流程
涉及的 EDA 工具
设计输入编辑器
用于设计输入
接受多种设计输入表达方式
原理图输入
状态图输入
波形输入
HDL 的文本输入方式
HDL 综合器
将综合的 HDL 语言转换成网表文件
仿真器
验证逻辑功能
验证时序功能
适配器(布局布线器)
完成目标系统在器件上的布局布线
下载器
将设计下载到对应的实际器件
实现硬件设计
Verilog HDL 基本语法
标识符
合法字符: 任意字母, 数字,"_" 下划线,"$" 美元符号
第一个字符必须为字母或下划线
区分大小写
常量
四值逻辑
"1,0" 分别对应信号 "有效(true)" 和 "无效(false)", 实际电路信号只有这两个值
x 为不定值, 表示模糊状态, 仿真器无法判定信号值
如: 一根信号线同时具有两个相反逻辑值(0,1)
z 为高阻态, 表示三态情形, 此时信号线不与驱动器相连
如: 三态门使能信号无效时产生一个 z 值
整型常量
+/-<位宽>'<进制><数字>
+/-<size>'<base><value>
进制有四种(不区分大小写)
二进制 b
八进制 o
十进制 d / 默认
十六进制 h
位宽为数值对应二进制数的宽度
- <size>
- 和
- < '>;<base > 和 < value > 之间可以允许空格
- <'>
- 和
- < base>
- 之间及数字内部不可空格
运算符
条件运算符
格式:<结果>=<条件表达式>?<表达式 1>:<表达式 2>;
计算条件表达式, 结果为真, 则将表达式 1 赋值给结果, 否则将表达式 2 赋值给结果
位拼接运算符
{操作数 1, 操作数 2,......, 操作数 n}
{重复次数{操作数}} // 复制运算符
时间控制语句
延时控制语句
用 "# 延时时间" 来表示
延时时间为指定的延时时间量, 以多个仿真时间单位给出
仿真时间单位须指定
分类
语句前延时
格式:# 延时时间语句;
仿真时遇到该语句结果为: 不立即执行语句, 等延时时间量过去再执行
单独延时
格式:# 延时时间;
仿真遇到该语句时不进行任何操作, 等待延时时间量过去
语句内延时
格式: 结果 = #延时时间表达式;
将赋值过程分成两步, 先计算表达式, 待延时时间量过去后, 将表达式的值赋给结果
这一语句计算顺序与前两种不同
事件控制语句
将某事件作为执行某操作的条件
分类
边沿敏感事件
e.g. @(posedge clk or negedge rst) c=a+b;@(d1 or d2 or d3) dout=d1^d2^d3;// 按位异或?
格式:@(事件)语句;
只要 "()" 中任一事件发生变化, 就会促使后面语句执行
电平敏感事件
赋值语句
连续赋值语句
格式: assign 结果 = 表达式;
所有变量均为 wire 型
过程赋值语句
always,initial 内对 reg 型变量赋值
阻塞赋值
使用 "="
在该语句结束时立即完成赋值操作
多条阻塞赋值语句存在时, 若前面的语句没有完成, 后面语句不能执行
非阻塞赋值
使用 "<="
在整个过程块结束时才完成赋值操作
整过过程份为两个操作: 同时开始计算所有右侧表达式, 给左侧所有结果赋值
在 always 中使用时, 综合成的电路为时序逻辑电路
编译预处理语句
以 "`" 开头, 结尾无 ";"
宏定义
示例
- `define width 8// 用 width 代替数字 8
- reg [`width-1:0] a,b,c;// 引用已定义宏名时需加上 "`"
时间标尺定义
两则示例: 1
- //`timescale 时间精度 / 时间单位
- `timescale 1ns/10ps // 表示时间单位 1ns, 时间精度 10ps
- module gate
- (
- input a,b,
- output out
- );
- or #(4.23,5.67) A1(out,a,b);
- endmodule
- // 上例中 4.23 延时值为 4.2ns,5.67 延时值为 5.7ns
- 2
- // 若改为下例, 则延时值分别为 42ns,57ns
- `timescale 1ns/10ps
- module gate
- (
- input a,b,
- output out
- );
- or #(4.23,5.67) A1(out,a,b);
- endmodule
基础程序实例
- ADDER
- // 半加器
- module half_add
- (
- input a,b,
- output cout,sum
- );
- assign sum=a^b;
- assign cout=a&b;
- endmodule
- //8 位全加器
- module adder8
- (
- input [7:0] a,b,
- input c,
- output reg [7:0] sum,
- output reg cout
- );
- always @(a or b or c)
- begin
- sum=a^b^c;
- cout=(a&b)|(a&c)|(b&c);
- end
- endmodule
- // 行为描述方式的 1 位全加器
- module full_add_2
- (
- input a,b,c,
- output reg sum,cout
- );
- always @(a or b or c)
- begin
- {cout,sum}=a+b+c;// 使用位拼接运算符很好诠释了全加器的实质
- end
- endmodule
- // 调用门级原件实现 1 位全加器
- module full_add
- (
- input a,b,c,
- output sum,cout
- );
- wire w,y1,y2,y3;
- and and1(y1,a,b);
- and and2(y2,a,c);
- and and3(y3,b,c);
- or or1(cout,y1,y2,y3);
- xor xor1(w,a,b);
- xor xor2(sum,w,c);
- endmodule
- // 用上例 1 位全加器构成 4 位全加器
- `include "full_add.v"
- module full_add4
- (
- input [3:0] a,b,
- input c,
- output [3:0] sum,
- output cout
- );
- wire c1,c2,c3;
- full_add u0(.a(a[0]),.b(b[0]),.c(c),.sum(sum[0]),.cout(c1));
- full_add u0(.a(a[1]),.b(b[1]),.c(c1),.sum(sum[1]),.cout(c2));
- full_add u0(.a(a[2]),.b(b[2]),.c(c2),.sum(sum[2]),.cout(c3));
- full_add u0(.a(a[3]),.b(b[3]),.c(c3),.sum(sum[3]),.cout(cout));
- endmodule
- MUX
- //2 选 1 多路数据选择器
- module mux2
- (
- input [1:0] a,b,
- input sel,
- output reg [1:0] q
- );
- always @(a or sel)
- begin
- if(sel)
- q=a;
- else
- q=b;
- end
- endmodule
- // 两种数据流描述 4 选 1 数据选择器
- module mux4_1a
- (
- input a,b,c,d,
- input s0,s1,
- output y
- );
- assign y=(~s1&~s0&a)|(~s1&s0&b)|(s1&~s0&c)|(s1&s0&d);
- endmodule
- module mux4_1b
- (
- input a,b,c,d,
- input s0,s1,
- output y
- );
- assign y=s1?(s0?d:c):(s0?b:a);
- endmodule
- COUNTER
- // 模 10 计数器
- module count10
- (
- input clk,rst,start,
- output reg cout,
- output [3:0] daout
- );
- reg [3:0] cnt;
- assign daout=cnt;
- always @(posedge clk or negedge rst)// 异步复位
- begin
- if(!rst)
- begin
- cnt<=0;
- cout<=0;
- end
- else if(start==1)
- begin
- if(cnt==10)
- begin
- cnt<=0;
- cout<=1;
- end
- else
- begin
- cnt<=cnt+1;
- cout<=0;
- end
- end
- end
- endmodule
- CODER/DECODER
- // 普通 8-3 编码器
- module code8_3
- (
- input [7:0] I,
- output reg [2:0] Q
- );
- always @(I)
- begin
- case(I)
- 8'b00000001:Q=7;
- 8'b00000010:Q=6;
- 8'b00000100:Q=5;
- 8'b00001000:Q=4;
- 8'b00010000:Q=3;
- 8'b00100000:Q=2;
- 8'b01000000:Q=1;
- 8'b10000000:Q=0;
- default:Q=3'bxxx;
- endcase
- end
- endmodule
- //8-3 优先编码器
- module code_8_3
- (
- input[7:0] I,
- input s,
- output reg [2:0] Q,
- output reg EO,GS
- );
- always @(s or I)
- begin
- if(s) begin Q=7;E0=1;GS=1;end
- else
- begin
- if(~I[7]) begin Q=0;EO=1;GS=0;end
- else if(~I[6]) begin Q=1;EO=1;GS=0;end
- else if(~I[5]) begin Q=2;EO=1;GS=0;end
- else if(~I[4]) begin Q=3;EO=1;GS=0;end
- else if(~I[3]) begin Q=4;EO=1;GS=0;end
- else if(~I[2]) begin Q=5;EO=1;GS=0;end
- else if(~I[1]) begin Q=6;EO=1;GS=0;end
- else if(~I[0]) begin Q=7;EO=1;GS=0;end
- else begin Q=7;EO=0;GS=1;end
- end
- end
- endmodule
- //3-8 译码器
- module decode3_8
- (
- input a,b,c,e1,e2,e3,
- output reg [7:0]Y
- );
- always @(a or b or c or e1 or e2 or e3)
- begin
- if((e1==1)&(e2==0)&(e3==0))
- case({c,b,a})
- 0:Y=8'b11111110;
- 1:Y=8'b11111101;
- 2:Y=8'b11111011;
- 3:Y=8'b11110111;
- 4:Y=8'b11101111;
- 5:Y=8'b11011111;
- 6:Y=8'b10111111;
- 7:Y=8'b01111111;
- default:Y=8'bX;
- endcase
- else
- Y=8'b11111111;
- end
- endmodule
- TRIGGER
- //D 触发器
- module dff
- (
- input clk,rst,d,
- output reg q
- );
- always @(posedge clk)
- begin
- if(rst)// 同步复位信号
- q<=0;
- else
- q<=d;
- end
- endmodule
- // 采用行为描述方式的基本 RS 触发器(if 语句嵌套)
- module RSff2
- (
- input R,S,
- output reg Q,QN
- );
- always @(R or S)
- if({R,S}==2'b01) begin Q<=0;QN<=1; end
- else if({R,S}==2'b10) begin Q<=1;QN<=0; end
- else if({R,S}==2'b10) begin Q<=Q;QN<=QN; end
- else begin Q<=1'bX;QN<=1'bX; end
- endmodule
- // 采用结构描述方式的基本 RS 触发器(体现逻辑)
- module RSff1
- (
- input R,S,
- output reg Q,QN
- );
- nand u1(Q,S,QN),
- u2(QN,R,Q);
- endmodule
- // 主从 JK 触发器
- module JKff2
- (
- input J,K,CP,
- output reg Q,QN
- );
- always @(negedge CP)
- if({J,K}==2'b00) begin Q<=Q;QN<=QN; end
- else if({J,K}==2'b01) begin Q<=0;QN<=1; end
- else if({J,K}==2'b10) begin Q<=1;QN<=0; end
- else if({J,K}==2'b11) begin Q<=~Q;QN<=~QN; end
- else begin Q<=1'bX;QN<=1'bX; end
- endmodule
- //T 触发器
- module tff
- (
- input clk,t,
- output reg q
- );
- always @(posedeg clk)
- begin
- if(t==0)
- q<=q;
- else
- q<=~q;
- end
- endmodule
来源: http://www.bubuko.com/infodetail-3330160.html