530 likes | 805 Views
VHDL 硬件描述语言及其应用 - 数字 IC 前端设计实例. 讲授内容. 数字 IC 设计中的前端设计内容 数字 IC 前端设计实例: UART 文档阶段 编码阶段 验证阶段. 数字 IC 设计流程. ……… SPEC …………. idea. initial. Verification. X=A and B Y=C nor D. A. X. B. Z. frontend. C. Y. D. Vdd. X. Vss. backend. V. B. A. A. X. VSS. B.
E N D
VHDL硬件描述语言及其应用 -数字IC前端设计实例VHDL硬件描述语言及其应用 -数字IC前端设计实例
讲授内容 • 数字IC设计中的前端设计内容 • 数字IC前端设计实例:UART • 文档阶段 • 编码阶段 • 验证阶段
………SPEC ………… idea initial Verification X=A and B Y=C nor D A X B Z frontend C Y D Vdd X Vss backend V B A A X VSS B physical Vss Vdd tape out
数字IC前端设计的层次 • 前端设计可分3个阶段: • 文档阶段:SPEC->设计文档 • 编码阶段:设计文档->HDL 代码 • 验证阶段:SPEC->验证平台->大量的验证
讲授内容 • 数字IC设计中的前端设计内容 • 数字集成电路前端设计实例:UART • 文档阶段 • 编码阶段 • 验证阶段
数字集成电路前端设计实例:UART UART预期操作环境
UART数据格式 数字集成电路前端设计实例:UART • 实例:通用异步收发器UART • APB外围总线的从设备 • 硬件流控制模式 :CTSN/RTSN握手协议 • 采用的数据格式是8个数据位,1个可选的奇偶校验位以及1个停止位
文档阶段 • SPEC->设计说明 • 定义接口:表格形式->接口一致性 • 子模块划分 • 子模块设计文档: • 设计描述:子模块设计指导->设计文档 • 实现方法说明:流程图、状态图、时序图 • 寄存器描述
1.SPEC • 模块功能: • 数据接收功能 • 数据发送功能 • 波特率生成器 • APB总线接口 • 数据流模式控制 • …… • 预期环境: • APB总线 • 其他UART • ……
1.SPEC • UART数据发送功能描述 • 当UART发送器被使能可进行发送操作。其操作为将待发送8位数据转换成一个串行数据,按位时钟输出到发送器的串行输出端口上。在停止位发送完成后,如果没有新的数据传送到发送保持寄存器中,则发送器串行数据输出端保持高电平。数据发送完成置发送移位寄存器空标识位为1。 • 当有新数据传送到空的发送保持寄存器中时,发送重新开始,发送移位寄存器空标识位被清0。假如发送器被禁止,则它将继续工作直到当前数据被完全发送完成。此时发送保持寄存器不能够重新装载数据。 • 如果采用流控制方式,CTSN输入必须保持低电平,这样数据才能被发送。如果在发送过程中,被设置成高,移位寄存器中的数据被发送,完成后发送端保持不变直到CTSN被重新设置成0。
2.定义接口 • APB接口: • PSEL: 输入-- slave select • PENABLE: 输入 -- strobe(选通脉冲) • PADDR(7 downto 0):输入-- address bus (byte) • PWRITE: 输入 --write • PWDATA(31 downto 0):输入-- write data bus • PRDATA (31 downto 0) :输出-- read data bus • UART接口: • RXD: 输入 • TXD: 输出 • CTSN: 输入 • RTSN: 输出 • 其他接口: • IRQ: 输出
3.子模块划分 • 按功能划分 • 按层次划分
4.子模块设计文档:设计描述 例:数据发送子模块功能设计描述 • 输入信号: • 发送时钟(txtick) :由波特率发生部件产生的基准时钟*8得到的位时钟,高电平有效 • 发送器使能(TE):高电平有效 • 发送器中断使能(TI):高电平有效 • 奇偶校验选择(PS):“0”表示偶校验,“1”表示奇校验 • 奇偶校验使能(PE):高电平有效 • 流控制使能(FL):高电平有效。 • 复位信号(rst):高电平有效 • 输出信号: • 发送移位寄存器空(TS):说明发送移位寄存器中的数据已经发送完毕 • 发送保持寄存器空(TH):说明先前的数据已经发送完毕,目前没有新的数据待发送。 • 数据发送输出端(TXD) • 中断输出信号(IRQ)
4.子模块设计文档:设计描述 • 数据发送:UART发送器的使能位(TE)控制,高电平有效。 • 数据由发送保持寄存器(thold)传送到发送移位寄存器(tshift)中,并且将其转换成一个串行队列,输出到发送器的串行输出端口TXD上。它将自动在8位有效数据前添加开始位,并在数据后添加一位可选的奇偶校验位和一位停止位。在停止位发送完成后,如果没有新的数据传送到发送保持寄存器中,则发送器串行数据输出端保持高电平,并且设置发送移位寄存器空标识位(TSRE)为1。 • 当有新数据传送到发送保持寄存器中时,判断发送保持寄存器空标识位(THRE)是否为1,如果为1且TI=1,则发出irq中断;如果TSRE=0,则发送开始,TSRE被清除。假如发送器被禁止,则它将继续工作直到当前数据被完全发送完成。此时发送保持寄存器不能够重新装载数据。 • 流控制方式:CTSN输入必须保持低电平,这样数据才能被发送。如果在发送过程中,CTSN被设置成高,移位寄存器tshift中的数据被发送,完成后发送端保持高电平不变,直到CTSN被重新设置成0。
4.子模块设计文档:模块实现方法 • 数字IC=数据通路+控制逻辑 • 数据通路:寄存器提取;存储器? • 控制逻辑: • 有限状态机:状态图,状态表…… • 硬连逻辑:流程图,时序图……
4.子模块设计文档:寄存器描述 • 寄存器的功能:保持历史值 • 数据通路:寄存器,计数器,移位器 • 控制输出信号的行为:命令、控制寄存器 • 如实反映当前电路工作状态:状态寄存器 • 方法: • 保存采样信号值->历史值和当前值比较 • 必要中间值:例如有限状态机的状态、跨周期信号等 • 模块输出信号寄存器输出
控制寄存器 该寄存器用来控制UART的操作 第0位:接收器使能(RE),高电平有效。 第1位:发送器使能(TE),高电平有效。 第2位:接收器中断使能(RI),高电平有效。 第3位:发送器中断使能(TI),高电平有效。 第4位:奇偶校验选择(PS),“0”表示偶校验,“1”表示奇校验。 第5位:奇偶校验使能(PE),高电平有效。 第6位:流控制使能(FL),高电平有效。 第7位:回送使能(LB),高电平有效。 第8位:外部时钟使能(EC),高电平有效,此时PIO[3]用作时钟。
UART状态寄存器 用来反映UART的状态 第0位:接收数据就绪(DR),说明在接收保持寄存器中,数据已经准备就绪。 第1位:发送移位寄存器空(TS),说明发送移位寄存器中的数据已经发送完毕。 第2位:发送保持寄存器空(TH),说明先前的数据已经发送完毕,目前没有新的数据待发送。 第3位:接收到暂停(BR),说明在数据接收过程接收到暂停信息。 第4位:溢出(OV),说明由于超出限度一个或多个字符而丢失。 第5位:奇偶错(PE),说明检测到奇偶错。 第6位:格式错(FE),说明检测到格式错。
编码阶段 • 编程前准备 • 设计思路:设计文档->RTL代码? • 编码风格 • 编码实例 • 文件层次化管理
编程前准备 • 遵守工程指定命名及格式规则 • 版本、设计日期、编者信息以及注释的使用 • 标识符对应具体功能含义:如thempty(transmit hold empty) • 标识符表明信号/变量属性:如cts_n,cts_,ctsn
设计思路 • 模块设计:考虑电路结构 • 串行:对输入的处理分步骤进行(process) • 并行:对到达的信号同时处理(多个等价process) • 流水线:多步骤、每个步骤同时处理 • 设计考虑: • 在内部模块之间的输入输出可采用组合逻辑,不同芯片之间必须采用寄存器输入输出(否则增加后端实现难度) • 尽量将组合电路和时序电路分开
编码风格 • 自顶向下规划 • 并发:并行等价进程规划 • 顺序:串行进程规划 • 自底向上编码 • 独立功能顺序编码:顺序语句->process • 并发进程:协调信号通信关系
自顶向下:并行等价进程规划 baudop : process(rst, r_p, uarti_p ) --baudrate/bitclock process -- baud rate generate -- rx/tx clock -- reset operation end process; apbop : process(rst, r_p, apbi) --apb operation -- read/write registers(APB slave Interface) -- reset operation -- update registers -- drive outputs end process; txrxop : process(rst, r_p, apbi) --transmit/receiver operation -- filter rx data -- transmitter operation -- receiver operation -- reset operation -- update registers -- drive outputs end process;
自顶向下:串行进程的规划 • 在最小信号间隔(clk)内更新信号及输出 uartop : process(rst, r, apbi, uarti ) --serial process variable v : uartregs; -- baud rate generate -- read/write registers(APB slave Interface) -- rx/tx clock -- filter rx data -- transmitter operation -- receiver operation -- reset operation -- update registers rin <= v; -- drive outputs end process;
编码实例:有限状态机实现 发送控制状态机
编码实例:有限状态机实现 case r.txstate is when idle => -- idle state if (r.txtick = '1') then v.tsempty := '1'; end if; if ((r.txen and (not r.thempty) and r.txtick) and (not ctsn)) = '1' then v.tshift := "10" & r.thold & '0'; v.txstate := data; v.tpar := r.parsel; v.irq := r.tirqen; v.thempty := '1'; v.tsempty := '0'; v.txclk := "00" & r.tick; v.txtick := '0'; end if; 数据发送代码段
编码实例:有限状态机实现 when data => -- transmit data frame if r.txtick = '1' then v.tpar := r.tpar xor r.tshift(1); v.tshift := '1' & r.tshift(10 downto 1); if r.tshift(10 downto 1) = "1111111110" then if r.paren = '1' then v.tshift(0) := r.tpar; v.txstate := parity; else v.tshift(0) := '1'; v.txstate := stopbit; end if; end if; end if; 数据发送代码段(续)
编码实例:有限状态机实现 when parity => -- transmit parity bit if r.txtick = '1' then v.tshift := '1' & r.tshift(10 downto 1); v.txstate := stopbit; end if; when stopbit => -- transmit stop bit if r.txtick = '1' then v.tshift := '1' & r.tshift(10 downto 1); v.txstate := idle; end if; end case; 数据发送代码段(续)
编码实例:控制信号 scaler := r.scaler - 1; --baud rate generate(tick) if (r.rxen or r.txen) = '1' then v.scaler := scaler; v.tick := scaler(11) and not r.scaler(11); if v.tick = '1' then v.scaler := r.brate; end if; end if; txclk := r.txclk + 1; --tx clk generate(8*tick) if r.tick = '1' then v.txclk := txclk; v.txtick := r.txclk(2) and not txclk(2); end if; 发送定标代码段:位时钟
编码实例:记录的使用->信号锁存 type uartregs is record rxen : std_logic; -- receiver enabled txen : std_logic; -- transmitter enabled rirqen : std_logic; -- receiver irq enable tirqen : std_logic; -- transmitter irq enable parsel : std_logic; -- parity select paren : std_logic; -- parity select flow : std_logic; -- flow control enable dready : std_logic; -- data ready rsempty : std_logic; -- receiver shift register empty (internal) tsempty : std_logic; -- transmitter shift register empty thempty : std_logic; -- transmitter hold register empty break : std_logic; -- break detected rhold : std_logic_vector(7 downto 0); rshift : std_logic_vector(7 downto 0); tshift : std_logic_vector(10 downto 0);
编码实例:记录的使用->信号锁存 thold : std_logic_vector(7 downto 0); irq : std_logic; -- tx/rx interrupt (internal) tpar : std_logic; -- tx data parity (internal) txstate : txfsmtype; txclk : std_logic_vector(2 downto 0); -- tx clock divider txtick : std_logic; -- tx clock (internal) rxstate : rxfsmtype; rxclk : std_logic_vector(2 downto 0); -- rx clock divider rxdb : std_logic_vector(1 downto 0); -- rx delay dpar : std_logic; -- rx data parity (internal) rxtick : std_logic; -- rx clock (internal) tick : std_logic; -- rx clock (internal) scaler : std_logic_vector(11 downto 0); brate : std_logic_vector(11 downto 0); rxf : std_logic_vector(7 downto 0); -- rx data filtering buffer end record;
编码实例:时钟同步 architecture rtl of uart is type rxfsmtype is (idle, startbit, data, parity, stopbit); type txfsmtype is (idle, data, parity, stopbit); type uartregs is record…… signal r, rin : uartregs; begin uartop : process(rst, r, apbi, uarti ) --serial process variable v : uartregs; …… rin <= v; end process; regs : process(clk)--signal registered by base clk begin if rising_edge(clk) then r <= rin; end if; end process; end architecture;
文件层次化管理 • 设计的层次化: • 顶层->底层:结构描述->行为描述 • 不同用途文件:命名规则区分,如_top,_package等 • 目录的层次化: • 工作目录 • 不同目的文件->不同目录,如src,sim,doc……
testbench Source top Testbench generate source package harness testcase 文件层次化管理
验证阶段 • 验证环境和测试方案->testbench • 根据设计文档确定验证点(testcase)->验证文档:描述每个验证点的目的、具体实现步骤 • 验证文档->testcase提取 • 覆盖率分析->不理想->回到第2阶段 • 记录验证结果->.log文件
验证环境架构及建立方式 • 基于软件模拟的层次式架构 • testcase层:由过程(procedure)调用组成 • 行为模型以及BFM:不可综合的代码,描述系统环境中可能的其他电路模型或行为 • testbench:验证配置 • testbench组织:configurations • 装配testcase,行为模型,BFM以及待测模块DUT
确定验证点 • testcase提取:procedures • 激励:从单一功能到复杂功能,辅以覆盖率工具 • 响应:针对具体testcase描述检查相关响应
例:数据发送进程testcase生成 testcase1:验证UART是否能够正确发送数据 a.保持发送时钟基准时钟*8得到的位时钟txtick; b.调用APB_write过程向UART 控制寄存器写入“000101010”; c.调用APB_write过程向UART 发送保持寄存器thold写入“10101010”; d.调用TXD_verify过程,并检测是否正确接收“10101010” testcase2:验证UART能否检验出奇偶校验错,并据此发出中断请求 a.保持发送时钟基准时钟*8得到的位时钟txtick; b.调用APB_write过程向UART 控制寄存器写入“000101010”; c. 调用APB_write过程向UART 发送保持寄存器thold写入“10101010”; d.调用TXD_verify过程,并检测是否正确接收“10101010”,偶校验无误,并接收到IRQ信号; e.调用APB_write过程向UART 控制寄存器写入“000111010”; f. 调用APB_write过程向UART 发送保持寄存器thold写入“10101010”; g.调用TXD_verify过程,并检测是否正确接收“10101010”,奇校验无误,并接收到IRQ信号; testcase3:溢出错误检查 testcase4:发送过程清TE testcase5:流控制检查 testcase提取
testcase实例-接收过程 --read RXD procedure for testbench procedure rxc(signal rxd : in std_logic; d: out std_logic_vector) is variable rxdata : std_logic_vector(7 downto 0); begin wait until rxd = '0'; wait for TXPERIOD/2; for i in 0 to 7 loop wait for TXPERIOD; rxdata(i):= rxd; end loop; wait for TXPERIOD ; d := rxdata; end; --end rxc testcase->procedure
testcase实例-发送过程(续) --transmit td(data) to txd procedure for testbench procedure txc(signal txd : out std_logic; td : integer) is variable txdata : std_logic_vector(10 downto 0); begin txdata := "11" & std_logic_vector(conv_unsigned(td, 8)) & '0'; for i in 0 to 10 loop wait for TXPERIOD ; txd <= txdata(i); end loop; end; --end txc
testcase实例-APB写数据过程(续) --read RXD procedure for testbench procedure apbwr(signal pclk : in bit; signal paddr: out std_logic_vector ; signal pwdata: out std_logic_vector ; signal pwrite: out std_logic; signal psel: out std_logic; signal penable: out std_logic; tadd: in std_logic_vector ; twdata: out std_logic_vector ) is begin wait on pclk; if pclk’event and pclk=‘0’ then paddr <= taddr; pwdata <= twdata; pwrite <= ‘1’;psel <= ‘1’; penable<=‘0’; end if; wait on pclk; if pclk’event and pclk=‘0’ then penable<=‘1’; end if; wait on pclk; if pclk’event and pclk=‘0’ then penable<=‘0’; end if; end; --end apbwr
architecture testbench_UART of testbench is UARTcheck:process variable data_tmp:std_logic_vecter(7 downto 0); begin rst<=0; wait for 20 ns; rst<=1;wait for 100 ns; rst<=0; --testcase 1 apbwr(pclk,paddr,pwdata,pwrite,psel,penable,”00000100”,”10101010”); apbwr(pclk,paddr,pwdata,pwrite,psel,penable,”00001000”,” 000101010”); rxc(txd,data_tmp); assert data_tmp =“10101010” report “UART transmit testcase1 error!!” severity error; --testcase 2 …… …… end process; --end UARTcheck end; --end testbench_UART 实例-UART testcase1
testbench • 1)将上述procedure在testbench的process中排列组合,分别调度就组成一个面向UART 的 黑盒子testbench generater • 2)把UART和testbench generater在顶层模块配置指定->testbench,则可进行模拟验证
testbench • 复用:将所有过程集中在package中,供所有设计者使用 • 在testbench中配置
覆盖率分析 • 代码覆盖率: EDA工具 +testcase • 验证施加的激励使得RTL代码都被覆盖了,验证仍然可能是不完整的 • 如果RTL代码根本就没有达到完整的覆盖,则验证肯定是不完整的。 • 功能覆盖率:边缘功能点(corner case) • 多功能交叉、组合 • 随机测试