基于FPGA 的8b10b编解码电路前端电路设计

基于FPGA 的8b10b编解码电路前端电路设计

摘 要

本设计是采用EDA技术设计的一种8B /10B 编解码电路,实现了在高速的串行数据传输中的直流平衡。该编解码电路设计大体上可以由五个模块构成,分别是默认编码模块、差异度计算模块、编码校正模块、并串转换模块、显示模块。
采用Verilog HDL 描述语言进行电路的设计、使用modelsim 10.2a 进行功能仿真、在通过Quartus II 13.1 进行FPGA逻辑综合和适配下载,并在Alter 公司的Cyclone IV E 的芯片EP4CE6F17C8 上实现并完成测试,最后用tcl语言编写约束脚本和启动文件,通过Synopsys的“Design Compiler”进行逻辑综合。
关键词: FPGA;Verilog HDL;8B10B编解码;tcl;逻辑综合。

前 言

可编程的“万能芯片” FPGA(Field-Programmable Gate Array)——现场可编程门阵列,是指一切通过软件手段更改、配置器件内部连接结构和逻辑单元,完成既定设计功能的数字集成电路。
FPGA可以实现怎样的能力,主要取决于它所提供的门电路的规模。如果门电路的规模足够大,FPGA通过编程可以实现任意芯片的逻辑功能,例如ASIC、DSP甚至PC处理器等。这就是FPGA为什么被称之为“万能芯片”的原因。
以硬件描述语言(Verilog或VHDL)所完成的电路设计,可以经过简单的综合与布局,快速的烧录至 FPGA 上进行测试,是现代 IC设计验证的技术主流。这些可编辑元件可以被用来实现一些基本的逻辑门电路。在大多数的FPGA里面,这些可编辑的元件里也包含记忆元件例如触发器(Flip-flop)或者其他更加完整的记忆块。
FPGA的核心具有可编程灵活性高、开发周期短、并行计算可编程灵活性高等优点。系统设计师可以根据需要通过可编辑的连接把FPGA内部的逻辑块连接起来,就好像一个电路试验板被放在了一个芯片里。一个出厂后的成品FPGA的逻辑块和连接可以按照设计者而改变,所以FPGA可以完成所需要的逻辑功能。

1总体电路结构设计

1.1 基本原理

在高速的串行数据传输中 ,传送的数据被编码 成自同步的数据流 ,就是将数据和时钟组合成单一 的信号进行传送 ,使得接收方能容易准确地将数据 和时钟分离 ,而且要达到令人满意的误码率 ,其关键 技术在于串行传输中数据的编码方法。目前大多数高速串行标准都采用 8B /10B 编码方案 ,例如光纤 通道 1、PCI - Exp ress、串行 ATA、以太网、XAU I、In2 finiBand和串行相连 SCSI等。使用 8B /10B编码技 术 ,较好地解决了以下问题。
(1)转换密度 :保证数据流中有足够的信号转 换。采用 8B /10B编码方法 ,数据流中连续的“1”或 连续的“0”不超过 5个 ,使接收端锁相环 (PLL)能正 常工作 ,避免接收端时钟漂移或同步丢失而引起数 据丢失。
(2) DC补偿 : 在高速的数据传输线路中 ,一般 采用差分信号 ,需要直流分量尽量小 ,而 8B /10B有 DC补偿功能 ,即链路中不会随着时间推移而出现 DC偏移。
(3)检错 : 8B /10B编码采用冗余方式 ,将 8位 的数据和一些特殊字符按照特定的规则编码成 10 位的数据 ,根据这些规则 ,能检测出传输过程中发生 错误的信息。
(4)特殊字符 : 8B /10B编码规定了一些特殊字符 ,可用作帧同步字符和其他的分隔符或控制字符。
8B/10B,也叫做8字节/10字节或8B10B。8B/10B方式最初由IBM公司于1983年发明并应用于ESCON(200M互连系统),由Al Widmer和Peter Franaszek在IBM的刊物“研究与开发”上描述。把 8位数据字节转换成串行传输使用的 10位码。8B /10B编码 保证了 1和 0的相对平衡组合 ,而与数据值无关 ,简 化了时钟恢复 ,降低了接收机成本。编码提供的其它位还促进了误码检测。8B /10B编码提供了构建串行通信使用的一套基础数据和控制字符。许多独立标准都以这个公共字符集为基础 ,定义更高的协议层。

1.2 电路总体图

在这里插入图片描述

1.3 电路功能框图

在这里插入图片描述
在这里插入图片描述

1.4 电路接口表

在这里插入图片描述

1.5 验证方案

为了验证编解码数据的正确性,首先在modelsim中仿真,通过观察信号的时序波形来对照真值表验证,在逻辑层面仿真成功后,再通过quartus II将各个模块烧录开发板,通过显示模块,将数据通过数码管显示出来进而进行验证数据的正确性,其中编码的数据来源于开发板上面的按键输入,解码的数据来源于编码数据的结果。
经过开发板的下载验证,通过结果分析可知,本方案符合课设设计任务书的要求,具有一定的可行性。

2模块设计

本设计按功能大体上可以分为8个子模块,分别为默认编码模块、差异度运算模块、编码校验模块、解码模块、并串转换模块、消抖模块、输入模块和显示模块。
在这里插入图片描述

2.1 默认编码模块设计

8b/10b编码是将一组连续的8位数据分解成两组数据,一组3位,一组5位,经过编码后分别成为一组4位的代码和一组6位的代码,从而组成一组10位的数据发送出去。相反,解码是将1组10位的输入数据经过变换得到8位数据位。
数据值可以统一的表示为DX.Y或KX.Y,其中D表示为数据代码,K表示为特殊的命令代码,X表示输入的原始数据的低5位EDCBA,Y 表示输入的原始数据的高3位HGF。
3B/4B 和 5B/6B 是通过映射机制进行编码的,这种映射机制已经标准化成相应的映射表
根据表格我们可以看出:5b/6b 编码的值可能有一种,还可能有两种。如果是前者,那么6b中的“1”的数量和“0” 的数量一定是相等的,如果是后者,那么编码6b的第两种情况为按位取反的结果。
在这里插入图片描述
所以,在进行编码过程中,先对5b/6b 进行默认编码,如果是第一种情况(即1的数量和0的数量相同),就在6b的最高位添加一个标记位,并且用0进行标记,否则(1的数量比0的数量多),就用1最为标记。3b/4b 默认编码过程与之相似,需要注意的是当3b=111时,有两组编码结果,为了避免10b的结果中0或1的数量连续超过4个的情况,4b码1000 和0111 这组编码出现的特殊情况外,其它的编码规则同上面分析的3B 码具有双值编码的情况,此时的编码取0001 和1110 这组编码。

2.2 差异度运算设计

8B/10B 编码中有两个重要的概念,不均等性( disparity )和极性偏差( runningdisparity , RD)。前者表示‘ 1’和‘ 0’个数的差值,其有如下规律:
(1)若 ABCDE 的 Disparity 值为 - 1, 那么在‘ RD- ’项中生成的 abcde 与 ABCDE 有一一对应的关系 , 并且 i=‘1’ , 此时除 ABCDE= ‘00011’外 abcde i 是唯一的 ;
(2)若 ABCDE 的 Disparity 值为 + 1, 那么在‘ RD-’项中生成的 abcde 与 ABCDE 有一一对应的关系 , 并且 i=‘0’, 此时除 ABCDE = ‘ 11100’外 abcdei 是唯一的 ;
(3)若 ABCDE 的 Disparity 值为 + 3, 那么在‘ RD-’项中生成的 abcde 与 ABCDE 有一一对应的关系 , 并且 i=‘0’, 此时 abcdei 是互为反码的两个值 ;
(4)若 ABCDE 的 Disparity 为其他值 , 此时 abcde i 具有互为反码的两个值 , 对这些特殊的‘RD –’项中的值可直接用查表法实现。
后者的取值分为以下三种:
(1)当码字中‘ 1’比‘ 0’多 , 或者 4B 码为 1100,或者 6B 码为 111000 时, 该码字被定义为正极性码 ,这个时候 RD 取正 ;
(2)当码字中‘ 1’比‘ 0’少 , 或者 4B 码为 0011,或者 6B 码为 000111 时, 该码字被定义为负极性码 , 这个时候 RD 取负 ;
(3)其他码字定义为中性码 , RD 取其前一码字的 RD 游程值。
在这里插入图片描述

2.3 编码校验模块设计

在3b4b默认编码模块中,编码产生的数据大致有两种情况,“0”和“1”的数量相等,或者“0”和“1”的数量不等,这两种情况和上一次数据的RD值组合产生几种结果:
为了方便判断各个状态的逻辑情况,将4b数据中1的个数多的情况标记为1,否则为0,6b数据同理。
在这里插入图片描述

2.4 解码模块设计

为得到快的解码处理速度 , 电路设计中采用数据解码并行处理完成, 而由数据 选择器控制选择输出数据的拓扑结构来实现 。8B /10B编码电路的原理是对 8B 数据编码时 将数据分为高 3位和低 5位两部分 , 分别进行 3B / 4B编码和 5B /6B编码结合在一起而生成最终的 10B数据 。 8B /10B数据解码电路 , 分为 3B /4B 解 码电路和 5B /6B解码电路两个部分, 共同实现解码 的完整数据解码。
由于解码不需要考虑差异度RD的值,从10bit 到 8bit ,所以解码的数据具有一一对应关系,可以通过4b到3b、6b到5b 直接查表来实现。可以参照附录I。
其中,需要注意的是,10bit是解码原始数据一共有2^10 1024种情况,但是与其对应的8bit的编码只有2^8 256种结果,这样如果解码的原始数据 10bit 不在编码产生的范围内,则需要解出一个错误标志信息,产生8bit 的数据为设定的默认值。
在这里插入图片描述

2.5 消抖模块设计

消抖模块主要的核心是对可能产生的按键信号进行判断是否是外部按键输 入而不是内部电平波动。一旦电平波动则开始计数,因为使用按键消抖时间为 20ms,实际消抖时间 20—40ms。 消抖只考虑的按键按下的抖动,忽略按键上弹的电平抖动,因为这段抖动不影响电路的功能和性能,如图为消抖模块内部接口波形图:
在这里插入图片描述
一旦检测到 KEY_IN 按键电平发生波动,为 0 开始计数,为 1 清除计数值,
当电平稳定为0时才能完成一次稳定计数到4000,产生消抖后的按键信号KEY。 而维持按键长时间不抬起,KEY 也一直为 0 不变。当按键 KEY_IN 抬起时,尽管 按键任然会产生电平波动,但是 KEY 信号稳定拉高为 1,这样完成一次消抖 同步到本地时钟的过程。下面列出消抖模块的端口信号表:
在这里插入图片描述

2.6 并串转换模块

由于传输中所用的是串行的数据流,所以,编码完成后需要将编号的并行10bit结果转换成串行的10bit,才能进行数据传输。
同理,在解码过程之前,也需要将串行的10bit转换成并行的以便于解码。
在这里插入图片描述
在这里插入图片描述
并行转换的数据为10bit,通过一个十进制的计数器进行控制,当计数值为0的时候,mask打开,并行数据送入移位寄存器中,并把最低位的一比特数据送出串行输出口。当计数值为非零时,mask选通前一个D触发器的输出,一个时钟上升沿,将数据向右移动移位,将数据送到串行输出端。

2.7 输入模块设计

本模块需要提供给FPGA的功能模块需要编码的8bit原始数据,这样整个系统才能运行,开发板上面可以利用的资源为四个物理按键,其中系统复位rstn占用一个,所以可以供用户自定义的按键有三个,本模块需要通过3个按键输入需要验证的8bit 并行数据。
本模块一共设计了三种工作模式,分别为计数输入模式、按键输入模式和随机模式。计数输入模式:通过按键控制输入的8bit数据逐次加一,这样可以编码出顺序的相邻数据。按键输入模式:通过两个按键控制,key1控制8bit的高4位,key2控制8bit的低4位,对key3的下降沿进行计数,即可指定输入数据的值。随机模式:通过一个key2按键进行输入,当检测到key2位低电平的时候,对计数变量cnt进行循环加一操作,计数变量cnt为8bit,最后将cnt的值通过持续赋值给输入,这样每当key2松开的时候,可以认为输入的数据为一个随机的值。

2.8 显示模块设计

本次使用的FPGA开发板上面的数码管为6个8段数码管,并且通过sel信号进行选通,drv信号输入显示编码数据。由于所有是数码管并联在一起,若想在不同的数码管上面显示不同的数据,需要分时复用数码管,首先对开发板上面的50M时钟进行分频,用分好频率的时钟进行移位和选通操作。
数值0—F分别译码成用于数码管显示的8bit显示码,分共阳和共阴的区别译码不同,需要根据不同的 FPGA 开发板来确定。八段数码管分别为 A,B,C,D,E,F,G,DP八段,前七段用于显示数字以及字母等字符,DP段在数码管上右下角,点亮后为小数点。对于多个数码管同一时刻只能点亮一个数码管。如图2.8所示:
在这里插入图片描述
由于本设计使用的FPGA开发板的数码管显示是采用的是共阳极数码管,且是六个并联的独立数码管,有6个数码管选通引脚,在这个设计中只需要四个数码管即可,现在列出共阳八段极数码管的显示码:
在这里插入图片描述
除了以上16个对应的显示码外,额外还有一个特殊的现实,仅仅用于电路复位是数码管上的现实,数码管仅g段点亮,其显示码为10111111。
需要显示的数据有编码输入的数据、编码产生的输出数据、解码的数据,所以6个数码管显示资源有些不足,这里采用了数码管动态游动显示的方式实现,定义一个选通信号,通过控制这个信号使数据中第一个4bit的位置的数码管熄灭,这样数据游走的同时,可以明显看出数据串的第一位,这样一来,就实现了数码管的高效率复用。

三 设计约束与逻辑综合

3.1设计约束

这里需要使用design compiler工具,可以参考design compiler使用教程

3.1.1约束策略

对于一个由时钟控制的数字逻辑电路来说,时序是最为重要的。encode_decode_top.v是本设计所要约束的文件。本设计定的时钟CLK的频率为50MHZ,即周期为20ns。输入为key[3:0],输出为led_sel[5:0]和led_drv[7:0],他们都是由CLK信号同步控制,所以这些信号延时约占时钟信号的35%,即输入输出延时设置为7ns。本次对此电路的综合约束需要分为以下几部分:对CLK时钟信号进行设置,对每个输入输出信号的约束,对扇出和驱动负载能力能度需要进行约束设置,最后输出报告。
以上约束只有对本电路结构非常熟悉才能对自己的时序约束更完善。
3.1.2 约束脚本
首先是读入源代码,也就是HDL文本描述的设计文件,此处不用制定目录,Design Compiler会在搜索目录中搜索。tcl语句如下:
read_verilog {encode_decode_top.v control_baud.v core_control.v decode_calculation.v running_disparity.v default_encode_3b_to_4b.v default_encode_5b_to_6b.v encode8b10b1.v encode_input_generate.v particular.v display2.v }
读入设计原文件后,一般设定当前设计,这样约束条件才可能有针对性的施加。tcl语句如下:
current_design encode_decode_top.v
设定当前设计后,要完成链接,也就是将设计与库链接起来,用于映射过程中搜索相应的单元,完成综合。tcl语句如下:
Link

检查设计,主要完成检查转换的设计。tcl语句如下:
check_design
然后对设计设定时序约束,这是最重要的一项约束,用于设定设计的工作速度。针对不同的设计部分,有不同的约束方法。针对本次设计,采用全同步,双时钟工作的实际情况。以下语句设定时钟及属性、输入输出信号时间余量。
设定名称为original_clk的时钟,由于采用50MHz的时钟,故设定时钟周期为20ns。
tcl语句如下:
create_clock [get_ports original_clk] -period 20 -waveform {10 20}
设定为理想时钟不对时钟网络进行驱动从而在使得综合工具在优化阶段
不去修改或移除该object,对时钟设置dont_touch属性,那么就可以避免在综合优化时对时钟上插入 buffer。tcl语句如下:
set_dont_touch_network [get_clocks " original_clk"]
set_ideal_network [get_ports " original_clk "]
告诉综合器不要对复位进行驱动。tcl语句如下:
set_dont_touch_network [get_ports rstn]
set_ideal_network [get_ports rstn]
设定输入信号最大时间延时。tcl语句如下:
set_input_delay -clock original_clk -max 7 [get_ports key1]
set_input_delay -clock original_clk -max 7 [get_ports key2]
set_input_delay -clock original_clk -max 7 [get_ports key3]
设定输出信号最大时间延时。tcl语句如下:
set_output_delay -clock original_clk -max 7 [get_ports {led_sel[5]}]
set_output_delay -clock original_clk -max 7 [get_ports {led_sel[4]}]
set_output_delay -clock original_clk -max 7 [get_ports {led_sel[3]}] set_output_delay -clock original_clk -max 7 [get_ports {led_sel[2]}]
set_output_delay -clock original_clk -max 7 [get_ports {led_sel[1]}]
set_output_delay -clock original_clk -max 7 [get_ports {led_sel[0]}]
set_output_delay -clock original_clk -max 7 [get_ports {led_drv[7]}]
set_output_delay -clock original_clk -max 7 [get_ports {led_drv[6]}]
set_output_delay -clock original_clk -max 7 [get_ports {led_drv[5]}]
set_output_delay -clock original_clk -max 7 [get_ports {led_drv[4]}]
set_output_delay -clock original_clk -max 7 [get_ports {led_drv[3]}] set_output_delay -clock original_clk -max 7 [get_ports {led_drv[2]}] set_output_delay -clock original_clk -max 7 [get_ports {led_drv[1]}]
set_output_delay -clock original_clk -max 7 [get_ports {led_drv[0]}]
检查时序。tcl语句如下:
check_timing
设定综合的操作条件。tcl语句如下:
set_operating_conditions -max slow -max_library slow.db:slow -min fast -min_library fast.db:fast
设定线负载模型,本设计选择tsmc18_wl20模型。tcl语句如下:
set_wire_load_model -name tsmc18_wl20 -library slow.db:slow
设定输出负载电容。tcl语句如下:

set_load -pin_load 3 [get_ports {led_sel[5]}]
set_load -pin_load 3 [get_ports {led_sel[4]}]
set_load -pin_load 3 [get_ports {led_sel[3]}]
set_load -pin_load 3 [get_ports {led_sel[2]}]
set_load -pin_load 3 [get_ports {led_sel[1]}]
set_load -pin_load 3 [get_ports {led_sel[0]}]
set_load -pin_load 3 [get_ports {led_drv[7]}]
set_load -pin_load 3 [get_ports {led_drv[6]}]
set_load -pin_load 3 [get_ports {led_drv[5]}]
set_load -pin_load 3 [get_ports {led_drv[4]}]
set_load -pin_load 3 [get_ports {led_drv[3]}]
set_load -pin_load 3 [get_ports {led_drv[2]}]
set_load -pin_load 3 [get_ports {led_drv[1]}]
set_load -pin_load 3 [get_ports {led_drv[0]}]

设定扇出最大负载能力。tcl语句如下:
set_max_fanout 20 [current_design]
驱动能力设定。tcl语句如下:

set_driving_cell -lib_cell PDIDGZ -library tpz973gwc [get_ports key1]
set_driving_cell -lib_cell PDIDGZ -library tpz973gwc [get_ports key2]
set_driving_cell -lib_cell PDIDGZ -library tpz973gwc [get_ports key3] 

设定输出网表的格式规则,以消除gate level nelist中的assign。tcl语句如下:
set verilogout_no_tri true
set_fix_multiple_port_nets -all -buffer_constants
最大能力进行综合。tcl语句如下:
compile -map high
输出时序报告。tcl语句如下:
rc > log/rc.log
输出网表。tcl语句如下:
write -f verilog -hier -o encode_decode.v
输出综合数据文件。tcl语句如下:
write -f ddc -hier -o encode_decode.ddc
输出延时文件。tcl语句如下:
write_sdf encode_decode.sdf
输出scl命令文件,在file>Save Info输出encode_decode.dc,文件中将会完整的包含所有tcl约束命令和各种环境、线载配置等。
除了以上报告外,还应该输出编译后对整个设计的各个方面的报告文件,如Report_area、Report_cells、Report_clock_skew、Report_constraints、Report_design、Report_nets、Report_path_group、Report_ports、Report_power、Report_reference、Report_timing_paths、Report_timing_requirements、 Report_wire_load等报告文件。

3.2逻辑综合

3.2.1 综合文件

首先在家目录(home)下建立 home/victor/dclab 作为本次实验 dc 的操作主目录。在 dclab 目录下,建立设计存放目录如 rtl/code、约束文件目录如 constraints、输出网表文件目录ntlist、报告输出目录report、文件目录work
等等,在综合前需要准备以下几类文件:
.synopsys_dc.setup文件即启动项文件:
在这个文件中,需要将所用到的库单元文件的路径和电路设计文件所存放的路径写入,以便软件在工作时能够找到这些文件并正确识别,本设计将它存放在
work目录下。主要配置libPath、Search_Path、Link_library、Target_library、
Symbol_library,本设计.synopsys_dc.setup文件具体配置见附录B。
*.v文件:
本设计为 8b10b编解码电路,有如下文件 encode_decode_top.v control_baud.v core_control.v encode8b10b1.v decode_calculation.v running_disparity.v encode_input_generate.v default_encode_3b_to_4b.v default_encode_5b_to_6b.v display2.v particular.v
本设计所使用电路描述语言为verilog HDL语言,所以需要将功能电路的设计文件准备好以便用于约束综合,这些文件应该在modelsim和Quartusii中编译通过的基础。
Tcl语句文件:
本次设计中使用的是命令界面,使用Tcl语言进行操作,所以需要准备好相应的Tcl命令以便对设计进行约束,本设计将它存放在constraints目录下。
库文件:
本设计采用的是tsmc公司的0.18um标准单元库的所有文件,存放在目录:/usr/eda/designKit/和/usr/synopsys/dc2016/下面,在.synopsys_dc.setup文件中配置时将这些文件的路径配置进去,启动软件的时候软件会加载.synopsys_dc.setup即可调用这些标准库文件。

3.2.1 综合环境

本次设计是运行在deepin Linux操作系统环境下的。Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。
本次课程设计所使用的综合工具Design Compiler(简称DC),是synopsys 公司的ASIC 综合器产品,它可以完成将硬件。描述语言所做的RTL级描述自动转换成优化的门级网表。DC 是工业界标准的逻辑综合工具,也是Synopsys 最核心的产品。它根据设计描述和约束条件并针对特定的工艺库将输入的VHDL或者Verilog 的RTL 描述自动综合出一个优化的门级电路。

3.2.1 综合过程

设计的主要完整步骤为:启动DC软件同时加载启动项文件→读入源代码→链接→设计检查→时序路径约束→综合环境约束→编译综合→输出报告→结束。 流程图大致如下图3.1所示:
在这里插入图片描述
以上为综合总体过程,接下来将要详细地进行逻辑综合操作,首先打开Linux中命令终端。进入以准备好的.synopsys_dc.setup文件所在路径。执行命令,打开Design Compiler。进入Tcl命令界面,命令如下:
cd /home/dcLab/work
lmgrd -c /usr/synopsys/license/synopsys.dat
design_version&
之后可以打开Design compiler软件,其启动终端如图所示:
在这里插入图片描述
Design compiler软件有GUI界面,既可以在Linux终端中进行Tcl语句约束和操作,也可在GUI图形界面操作,其界面如图所示:
在这里插入图片描述
打开软件的时候软件会调用已经配置好的.synopsys_dc.setup 文件,定位到标准文件库中和搜索路径。 接下来就可以导入已经准备好的文件,被存放在之前在家目录下自己建立的 code目录下,其完整路径为/home/victor/dclab /rtl/code中的文件。导入时DC会初步检查代码的问题,没有问题才能导入成功。下一步就是要与库文件进行链接,如下图3.4所示:
在这里插入图片描述
链接成功则.synopsys_dc.setup 文件配置正确,下一步进行时序约束和环境约束,在constraints目录下存放着书写好的Tcl约束命令,可以一步导入约束命令快速完成约束,也可以在GUI界面一步步进行约束的必要操作,本设计在终端进行一步输入操作,之后进行编译和分析报告并作出修改,如图所示:
在这里插入图片描述

四 报告分析

完成上一节的约束操作后,完成编译就可以查看输出各种关于设计的报告分析,通过报告分析可以得出设计中的各种缺陷和问题,以及约束是否有错误、违反约束原则,然后进行优化和修改达到满意的结果。

4.1约束报告

约束报告将给出之前关于本设计的约束是否违反了约束规则或者导致设计的性能变差,以及有没有对时序要求完成合适的约束。本设计约束没有违反约束规则,具体报告如下所示:

****************************************
Report : constraint
        -all_violators
        -max_area
        -max_delay
        -max_leakage_power
        -max_dynamic_power
        -max_total_power
        -cell_degradation
        -max_toggle_rate
        -max_capacitance
        -max_fanout
        -max_transition
        -multiport_net
Design : encode_decode_top
Version: L-2016.03-SP1
Date   : Fri Jun 21 13:50:36 2019
****************************************
This design has no violated constraints.
 

4.2时序报告

电路有不同的信号时序路径(Timing Path),每条路径都有一个起点和一个
终点。起点是电路的输入端口或电路中寄存器的时钟管脚,终点是电路的输出端
口或时序器件(sequential devices)中除时钟管脚外的其它输入管脚。生成的时序报告由4 个部分组成:路径信息部分(Path Information Section),路径延
时部分(Path Delay Section),路径要求部分(Path Required Section),总结部分(Summary Section),本设计时序报告如下所示:

****************************************
Report : timing
        -path full
        -delay max
        -max_paths 1
        -sort_by group
Design : encode_decode_top
Version: L-2016.03-SP1
Date   : Sun Jul  7 16:27:37 2019

Operating Conditions: slow   Library: slow
Wire Load Model Mode: top
  Startpoint: kongzhi/segxianshi/cnt1s_reg[0]
              (rising edge-triggered flip-flop clocked by original_clk)
  Endpoint: kongzhi/segxianshi/cnt1s_reg[28]
            (rising edge-triggered flip-flop clocked by original_clk)
  Path Group: original_clk
  Path Type: max
  Des/Clust/Port     Wire Load Model       Library
  encode_decode_top  tsmc18_wl20           slow
  Point                                                   Incr       Path
  clock original_clk (rise edge)                         10.00      10.00
  clock network delay (ideal)                             0.00      10.00
  kongzhi/segxianshi/cnt1s_reg[0]/CK (DFFRHQX1)           0.00      10.00 r
  kongzhi/segxianshi/cnt1s_reg[0]/Q (DFFRHQX1)            1.08      11.08 r
  kongzhi/segxianshi/add_47/A[0](display2_DW01_inc_0)		 0.00 	   11.08 r                                                         
  kongzhi/segxianshi/add_47/U1_1_1/CO (ADDHXL)            0.45      11.54 r
  kongzhi/segxianshi/add_47/U1_1_2/CO (ADDHXL)            0.43      11.97 r
  kongzhi/segxianshi/add_47/U1_1_3/CO (ADDHXL)            0.43      12.41 r
  kongzhi/segxianshi/add_47/U1_1_4/CO (ADDHXL)            0.43      12.84 r
  kongzhi/segxianshi/add_47/U1_1_5/CO (ADDHXL)            0.43      13.28 r
  kongzhi/segxianshi/add_47/U1_1_6/CO (ADDHXL)            0.43      13.71 r
  kongzhi/segxianshi/add_47/U1_1_7/CO (ADDHXL)            0.43      14.14 r
  kongzhi/segxianshi/add_47/U1_1_8/CO (ADDHXL)            0.43      14.58 r
  kongzhi/segxianshi/add_47/U1_1_9/CO (ADDHXL)            0.43      15.01 r
  kongzhi/segxianshi/add_47/U1_1_10/CO (ADDHXL)           0.43      15.45 r
  kongzhi/segxianshi/add_47/U1_1_11/CO (ADDHXL)           0.43      15.88 r
  kongzhi/segxianshi/add_47/U1_1_12/CO (ADDHXL)           0.43      16.31 r
  kongzhi/segxianshi/add_47/U1_1_13/CO (ADDHXL)           0.43      16.75 r
  kongzhi/segxianshi/add_47/U1_1_14/CO (ADDHXL)           0.43      17.18 r
  kongzhi/segxianshi/add_47/U1_1_15/CO (ADDHXL)           0.43      17.62 r
  kongzhi/segxianshi/add_47/U1_1_16/CO (ADDHXL)           0.43      18.05 r
  kongzhi/segxianshi/add_47/U1_1_17/CO (ADDHXL)           0.43      18.49 r
  kongzhi/segxianshi/add_47/U1_1_18/CO (ADDHXL)           0.43      18.92 r
  kongzhi/segxianshi/add_47/U1_1_19/CO (ADDHXL)           0.43      19.35 r
  kongzhi/segxianshi/add_47/U1_1_20/CO (ADDHXL)           0.43      19.79 r
  kongzhi/segxianshi/add_47/U1_1_21/CO (ADDHXL)           0.43      20.22 r
  kongzhi/segxianshi/add_47/U1_1_22/CO (ADDHXL)           0.43      20.66 r
  kongzhi/segxianshi/add_47/U1_1_23/CO (ADDHXL)           0.43      21.09 r
  kongzhi/segxianshi/add_47/U1_1_24/CO (ADDHXL)           0.43      21.52 r
  kongzhi/segxianshi/add_47/U1_1_25/CO (ADDHXL)           0.43      21.96 r
  kongzhi/segxianshi/add_47/U1_1_26/CO (ADDHXL)           0.43      22.39 r
  kongzhi/segxianshi/add_47/U1_1_27/CO (ADDHXL)           0.43      22.82 r
  kongzhi/segxianshi/add_47/U2/Y (XOR2X1)                 0.40      23.22 f
  kongzhi/segxianshi/add_47/SUM[28] (display2_DW01_inc_0) 0.00      23.22 f
  kongzhi/segxianshi/U113/Y (AND2X1)                      0.35      23.57 f
  kongzhi/segxianshi/cnt1s_reg[28]/D (DFFRHQX1)           0.00      23.57 f
  data arrival time                                                 23.57
  clock original_clk (rise edge)                         30.00      30.00
  clock network delay (ideal)                             0.00      30.00
  kongzhi/segxianshi/cnt1s_reg[28]/CK (DFFRHQX1)          0.00      30.00 r
  library setup time                                     -0.43      29.57
  data required time                                                29.57

  -------------------------------------------------------------------------
  data required time                                                29.57
  data arrival time                                                -23.57
  -------------------------------------------------------------------------

  slack (MET)                                                        5.99
***** End Of Report ***** 
 

4.3 面积报告

面积报告中列出了设计的端口、单元、线网和引用的数目。设计的面积被分为组合、非组合以及互连线。分别显示出组合逻辑面积,时序逻辑面积,估计的互联线面积,单元器件总面积。本设计的面积报告如下:

****************************************
Report : area
Design : encode_decode_top
Version: L-2016.03-SP1
Date   : Fri Jun 21 13:51:54 2019
****************************************
Library(s) Used:
    slow (File: /usr/eda/designKit/UMCArtisan18/aci/sc-x/synopsys/slow.db)
Number of ports:                          323
Number of nets:                          1106
Number of cells:                          781
Number of combinational cells:            692
Number of sequential cells:                76
Number of macros/black boxes:               0
Number of buf/inv:                        144
Number of references:                       1
Combinational area:              12530.549085
Buf/Inv area:                     1892.721663
Noncombinational area:            5125.982357
Macro/Black Box area:                0.000000
Net Interconnect area:          202814.354431
Total cell area:                 17656.531442
Total area:                     220470.885873
***** End Of Report *****

设计总结

通过这次数字集成电路的课程设计,我巩固了自己的 FPGA 的相关知识,更加深入的掌握了 verilog HDL 语言的用法 。开始设计的过程中,遇到了很多困难,原理搞不懂,软件使用不熟练,verilog HDL 语法问题,其中对于相关资料的检索也是一个我们都比较弱的方面。
经过询问老师后,以及老师给的指导和理论课程的跟进,外加上课讲解的许多典型电路的例子,自己也在bing和google中搜索到了一些题目相关的资料,最后在eetop(易特创新网)中找到了一个比较好的例子,通过对它的探索,经过不断的仿真与调试,逐渐实现了课题要求的功能,随后逐步完善代码,完成了设计任务。
本次的课程设计是继续上学期的EDA技术与FPGA应用的课程设计做的。重点在于运用Liunx环境下的design compiler软件进行逻辑综合,对电路各部分进行约束,对于一个设计从提出到实际生产使用的一步步流程越来越深刻。 而其中的难点在于我们对于Linux系统环境的接触比较少,导致这个软件的安装破解以及环境变量的配置比较困难,其中遇到了许多问题,而解决这些问题花费了大量的时间和精力,不过经过这个过程后,我对于Linux的知识也是更加的深入了,我相信这将会对以后Linux系统下的软件使用会有所帮助。
8b/10b 编解码在高速串行网络数据数据传输中充当不可或缺的角色,通过本次的课程设计,我明确它的传输转换原理,对于以后 FPGA 的学习,更能加深理解。

参考文献

[1] Lattice Semiconductor 8b/10b Encoder/Decoder
[2] A DC-Balanced, Partitioned-Block, 8B/10B Transmission Code
[3] 8b/10b Encoder v5.0 XILINX
[4] 8B/10B 编码器的设计及实现 李宥谋
[5] 8B_10B 编码详解 _灵思迈_新浪博客

附录I:程序源代码

//控制模块
module core_control(original_clk,rstn,led_sel,led_drv,key1,key2,key3);
/*
用于连接各个模块,控制输入输出, 显示
*/
input original_clk,rstn;
output [7:0] led_drv;
output [5:0] led_sel;
input key1,key2,key3;
//指定 端口的类型
wire original_clk,rstn;
wire [7:0] led_drv;
wire [5:0] led_sel;
wire key1,key2,key3;
wire [8:0]  original_in;
wire [9:0]  out;
wire [9:0]  out_standard;
wire [43:0] data;
wire rd;
wire correct;
wire check;
wire decode_in;
wire [7:0] decode_out;
assign check = (out_standard==out) ? 1 : 0 ;
//空的 内容  因为起始的第一个4bit 灯的不能用的(灭了)作为游动 标志
assign data[43:40] = {4'b0};
//将输入内容送显示模块
assign data[39:28] = {3'b0,original_in};
// 将输出结果送显示模块
assign data[27:16] = {2'h0,out};
//将rd送显示模块
assign data[15:12] = {3'b000,rd};
//将检查标志位送显示模块
assign data[11:8] = {3'b000,correct};
//将解码的结果送显示模块
assign data[7:0] = {decode_out};
//标准真值表校验
//original_in,out_standard,rd_standard,key1,rstn
encode_standard biaozhun(
	.original_in(original_in),
	.out_standard(out_standard),
	.rd(rd),
	.key1(key1),
	.rstn(rstn)
	);
//编码主模块例化
encode8b10b1 en8to10(
	.original_in(original_in),
	.original_clk(original_clk),
	.rstn(rstn),
	.key1(key1),
	.rd(rd),
	.out(out)
	);


//解码计算模块例化
decode_calculation de10to8(
.decode_in(out),
.decode_out(decode_out),
.correct(correct)
);

//显示模块	
display2 segxianshi(
	.original_clk(original_clk),
	.led_sel(led_sel),
	.led_drv(led_drv),
	.rstn(rstn),
	.data(data)
	);

//输入模块
encode_input_generate shuru(
	.original_clk(original_clk),
	.key1(key1),
	.key2(key2),
	.key3(key3),
	.original_in(original_in),
	.rstn(rstn)
	);	
Endmodule
 
//编码主模块
module encode8b10b1(original_in,original_clk,rstn,key1,rd,out);

//定义输入输出端口
input original_clk,rstn;
input [8:0] original_in;
output rd;
output [9:0] out;
input key1;
//指定 端口的类型
wire [8:0] original_in;
wire original_clk,rstn;
wire [7:0] led_drv;
wire [5:0] led_sel;
wire key1,key2,key3;
// 定义中间变量
reg rd_temp;		
reg [7:0] in;		
wire [4:0] in_5b_to_6b;
wire [2:0] in_3b_to_4b;
wire [6:0] out_5b_to_6b;
wire [4:0] out_3b_to_4b;
wire [9:0] out_common;
wire [9:0] out_particular;
wire [9:0] out;
wire [11:0] in12b;
wire rd;
reg k;
wire rd_common;
wire rd_particular;
always@(posedge key1 or negedge rstn)begin
if(!rstn)
	in <= 0;
else
	in <= original_in[7:0];
end

always@(posedge key1 or negedge rstn)begin
if(!rstn)
	k <= 0;
else
	k <= original_in[8];
end

always@(posedge key1 or negedge rstn)begin
if(!rstn)
	rd_temp <= 0;
else
	rd_temp <= rd;
end

assign in12b = {out_3b_to_4b[4:0],out_5b_to_6b[6:0]};
assign in_5b_to_6b = in[4:0];
assign in_3b_to_4b = in[7:5];
assign out = k ? out_particular : out_common;
assign rd = k ? rd_particular:rd_common;

//5b6b默认编码模块
default_encode_5b_to_6b en56(
	.in_5b_to_6b(in_5b_to_6b),
	.out_5b_to_6b(out_5b_to_6b)
	);

//3b4b默认编码模块
default_encode_3b_to_4b en34	(
	.in_3b_to_4b(in_3b_to_4b),
	.out_3b_to_4b(out_3b_to_4b),
	.out_5b_to_6b(out_5b_to_6b)
	);
	
//差异度计算模块	
running_disparity running_disparity(.rd_temp(rd_temp),
	.in12b(in12b),
	.out_common(out_common),
	.rd_common(rd_common)
	);
//特殊编码模块
particular particular(
	.in_particular(in),
	.out_particular(out_particular),
	.rd_temp(rd_temp),
	.rd_particular(rd_particular)
	);	
Endmodule
 
//3b到4b默认编码模块
module default_encode_3b_to_4b(out_5b_to_6b,in_3b_to_4b,out_3b_to_4b);
/*	
2. 3b到4b默认编码 有三种情况
	1:一的数量和零的数量相等,此时标志位为0	
	2:一的数量是3个,零的数量是1个 ,此时标志位为1
			其中 3b为111时,其编码取决于 6b 的结果
	*/
input [2:0] in_3b_to_4b;
input [6:0] out_5b_to_6b;
output [4:0] out_3b_to_4b;	
wire [6:0] out_5b_to_6b;			
wire [2:0] in_3b_to_4b;
reg [4:0] out_3b_to_4b;	
always @ (in_3b_to_4b)begin
	case (in_3b_to_4b)
		3'b000: out_3b_to_4b <= 5'b11011;
		3'b001: out_3b_to_4b <= 5'b01001;
		3'b010: out_3b_to_4b <= 5'b00101;
		3'b011: out_3b_to_4b <= 5'b01100;
		3'b100: out_3b_to_4b <= 5'b11101;
		3'b101: out_3b_to_4b <= 5'b01010;
		3'b110: out_3b_to_4b <= 5'b00110;
		3'b111: begin 
						if(!out_5b_to_6b[6] && (out_5b_to_6b[0]==out_5b_to_6b[1]))
							out_3b_to_4b <= 5'b10111;
						else
							out_3b_to_4b <= 5'b11110;				end
	endcase end endmodule
//5b到6b默认编码模块
module default_encode_5b_to_6b(in_5b_to_6b,out_5b_to_6b);
/*
1. 5b到6b默认编码 有两种情况 
	1:一的数量和零的数量相等,此时标志位为0	
	2:一的数量是4个,0的数量是2个,此时标志位为1
	*/
input [4:0] in_5b_to_6b;
output [6:0] out_5b_to_6b;	
wire [4:0] in_5b_to_6b;
reg [6:0] out_5b_to_6b;
always @ (in_5b_to_6b)begin
	case(in_5b_to_6b)				
	//out_5b_to_6b 的 最高位用于标志 1的数量和0 的数量是否一样, 一样 为0,否则,为1,即代表有4个1
				5'h00:	 out_5b_to_6b <= 7'b1100111;
				5'h01:	 out_5b_to_6b <= 7'b1011101;
				//…
				5'h1f:	 out_5b_to_6b <= 7'b1101011;
	Endcase end endmodule
//差异度计算和10bit校验模块
module running_disparity(rd_temp,rd_common,in12b,out_common);
input rd_temp;
input [11:0] in12b;
output [9:0] out_common;
output rd_common;
wire rd_temp;
wire [11:0] in12b;
reg [9:0] out_common;
reg rd_common;
always@(in12b or rd_temp)begin
case({in12b[11],in12b[6],rd_temp})
	3'b000: begin 	out_common <= {	in12b[5:0]	,	in12b[10:7]	} ; rd_common <= rd_temp ; 	end
	3'b001: 
	begin
 	out_common <= (in12b[5:0]==111000)?{~in12b[5:0],in12b[10:7]}:{in12b[5:0],in12b[10:7]} ; 
	rd_common <= rd_temp ; 	
	end
	3'b010: begin 	out_common <= {	in12b[5:0]	,	in12b[10:7]	} ; 	rd_common <= ~rd_temp ; 	end
	3'b011: begin 	out_common <= {	~in12b[5:0]	,	in12b[10:7]	} ; 	rd_common <= ~rd_temp ; 	end
	3'b100: begin 	out_common <= {	in12b[5:0]	,	in12b[10:7]	} ; rd_common <= ~rd_temp ; 	end
	3'b101: 
	begin 	
	out_common <= (in12b[5:0]==111000)?{~in12b[5:0],~in12b[10:7]}:{	in12b[5:0],~in12b[10:7]} ; 
	rd_common <= ~rd_temp ; 	
	end
	3'b110: begin 	out_common <= {	in12b[5:0]	,	~in12b[10:7]	} ; rd_common <= ~rd_temp ; 	end
	3'b111: begin 	out_common <= {	~in12b[5:0]	,	in12b[10:7]	} ; rd_common <= ~rd_temp ; 	end
Endcase end endmodule 
//显示模块
moduledisplay2(original_clk,led_sel,led_drv,rstn,key1,key2,key3,data);
//定义输入输出
input [43:0] data;
input original_clk,rstn;
input key1,key2,key3;
output [7:0] led_drv;
output [5:0] led_sel;
// 定义输入输出接口类型
wire [43:0] data;		
//需要显示的动态数据,其中有4bit 作为 标志位 不能使用,所以可以用的位数有36bit 可以显示 9个4bit数据
wire original_clk,rstn;
//原始的时钟输入,时钟频率50M HZ,复位接按键
wire key1,key2,key3;  
//三个按键控制信号,可以控制进行输入数据
reg [7:0] led_drv;		
//最终的seg译码信号,控制数码管显示内容
wire [5:0] led_sel;		
//最终的显示输出,对外端口
//定义各种中间变量的类型
reg [23:0] contain;
//contain 是 6个数码管的当前显示内容, 一个数码管显示4bit 所以 contain 一共24bit 
reg [7:0] cnt;
wire clk;
//显示需要的经过适度分频的时钟信号,clk为分频模块是输出时钟信号
reg [3:0] led_drv_temp;
//显示码的中间变量,表示当前一个周期 显示的 4bit 数据内容
reg [5:0] led_sel_temp;
//显示输出的中间变量,因为需要加一个控制信号,所以要先有一个中间值 暂存过程
reg [5:0] switch;
// 显示数码管开关信号 控制 做为动态显示的一个灭的标志,否则 无法判断这个一组数据的起始位
reg [28:0] cnt1s;
//计数信号,通过计数,实现分频,进而控制数码管 在分时复用的基础上,加上游动显示
//接近1秒钟的分频,50M时钟 ,分 2的25次幂 频 时间 可以作为移位的驱动信号
always@(posedge original_clk or negedge rstn)begin
if(!rstn) 
	cnt1s =0;
else 
	if(	cnt1s[28:25]==4'b1011	)
	//直接对其高bit位进行译码,运算 省去了 中间的计数信号,即将计数值直接作为 分好频 并且记好数的信号
		cnt1s[28:25] = 4'b0000;
	else	cnt1s=cnt1s+1'b1;
end
// 25进制计数器,的最高位,作为移动信号
	// 对移动信号计数,5进制计数
	// 计数值译码
always@(cnt1s)begin
	case(cnt1s[28:25])
	//不同的计数值,对应不同的数据内容,进行动态游动 移位
	4'b0000:	 contain <= 		data[43:20] 							;
	4'b0001:	 contain <= 		data[39:16] 							;
	4'b0010:	 contain <= 		data[35:12] 							;
	4'b0011:	 contain <= 		data[31:8]   							;
	4'b0100:	 contain <= 		data[27:4]   							;
	4'b0101:	 contain <= 		data[23:0]   							;
	4'b0110:	 contain <= {	data[19:0]	,	data[43:40]	}	;
	4'b0111:	 contain <= {	data[15:0]	,	data[43:36]	}	;
	4'b1000:	 contain <= {	data[11:0]	,	data[43:32]	}	;
	4'b1001:	 contain <= {	data[7:0]	,	data[43:28]	}	;
	4'b1010:	 contain <= {	data[3:0]	,	data[43:24]	}	;
	default:	 contain <= 23'h0	;                                                     
	endcase         
end
// data是要显示的全部比特数据
// contain是当前显示的比特数据
// 起始位 数码管灭 标记 开关控制
always@(cnt1s)begin
	case(cnt1s[28:25])
	//对cnt1s进行相应译码,选择控制 灭的数码管的位置
		4'b0000:	switch <= 6'b100000;
		4'b0001:	switch <= 6'b000000;
		4'b0010:	switch <= 6'b000000;
		4'b0011:	switch <= 6'b000000;
		4'b0100:	switch <= 6'b000000;
		4'b0101:	switch <= 6'b000000;
		4'b0110:	switch <= 6'b000001;
		4'b0111:	switch <= 6'b000010;
		4'b1000:	switch <= 6'b000100;
		4'b1001:	switch <= 6'b001000;
		4'b1010:	switch <= 6'b010000;
	   	default:  	switch <= 6'b000000;
						   
	endcase 
end
//选通开关 加入
assign led_sel = switch|led_sel_temp;
//持续赋值,让led_sel 最终的信号 是在switch的控制下进行 的
// 选择信号移位操作
always@(posedge clk or negedge rstn )begin
	if(!rstn)
		led_sel_temp <= 6'b000000;
	else
		if(led_sel_temp==6'b000000)
			// led_sel <= (switch[5:0])|(6'b111110);
			led_sel_temp <= 6'b111110;
		else
			// led_sel = led_sel
			led_sel_temp = {led_sel_temp[4:0],led_sel_temp[5]};
end
// 选择信号 对应数据传递
always@(led_sel_temp or rstn)begin
	// begin
		case(led_sel_temp)
			6'b111110:led_drv_temp <= contain[3:0];
			6'b111101:led_drv_temp <= contain[7:4];
			6'b111011:led_drv_temp <= contain[11:8];
			6'b110111:led_drv_temp <= contain[15:12];
			6'b101111:led_drv_temp <= contain[19:16];
			6'b011111:led_drv_temp <= contain[23:20];
			default:led_drv_temp <= 4'b0000;
		endcase
end
// 显示内容 seg 数码管译码
always@(led_drv_temp or rstn or cnt1s)begin
if(!rstn)
		led_drv  <=	8'b10111111;  //H_
	else begin
	case(led_drv_temp)
	// 一个数码管显示的4bit数据显示seg译码
		4'b0000:		led_drv  <=	8'b11000000;
		4'b0001:		led_drv  <=	8'b11111001;
		4'b0010:		led_drv  <=	8'b10100100;
		4'b0011:		led_drv  <=	8'b10110000;
		4'b0100:		led_drv  <=	8'b10011001;
		4'b0101:		led_drv  <=	8'b10010010;
		4'b0110:		led_drv  <=	8'b10000010;
		4'b0111:		led_drv  <=	8'b11111000;
		4'b1000:		led_drv  <=	8'b10000000;
		4'b1001:		led_drv  <=	8'b10010000;
		4'b1010:		led_drv  <=	8'b10001000;
		4'b1011:		led_drv  <=	8'b10000011;
		4'b1100:		led_drv  <=	8'b11000110;
		4'b1101:		led_drv  <=	8'b10100001;
		4'b1110:		led_drv  <=	8'b10000110;
		4'b1111:		led_drv  <=	8'b10001110;
		// default:		led_drv  <=	8'b10000001;  //H_
	endcase
	end
end
control_baud fenpin(.SAMPLING(clk),.CLK(original_clk),.RSTN(rstn));
//连接 分频模块 对原始时钟进行分频
Endmodule
//输入模块
// `timescale 1ns/1ns
module encode_input_generate(key1,key2,key3,original_in,original_clk,rstn);
//本模块是产生 编码模块需要的输入数据的
input key1,key2,key3;
input rstn,original_clk;
output [8:0] original_in; 
wire key1,key2,key3;
wire rstn,original_clk;
wire [8:0] original_in;
//随机模式
reg cnt0;
reg [7:0] cnt1;
assign original_in[8:0] = {cnt0,cnt1[7:0]};
always@(posedge original_clk or negedge rstn)begin
	if(!rstn)cnt1 <= 0;
	else begin
		if(!key2) 
		cnt1 <= cnt1+1'b1;
	end
end
//key3用于 标记 特殊值
always@(posedge key3 or negedge rstn)begin
if(!rstn)cnt0 <= 0;
	else begin
	cnt0 <= !cnt0;end end
//按键输入模式
reg [3:0] cnt1;
reg [3:0] cnt0;
// cnt0为低四位输入,cnt1为高四位输入
assign original_in = {cnt1,cnt0};
// key3控制低4位输入
always@(posedge key3 or negedge rstn)begin
	if(!rstn)
		cnt0 <= 0;
	else
		cnt0 = cnt0+1'b1;
end
always@(posedge key2 or negedge rstn)begin
	if(!rstn)
		cnt1 <= 0;
	else
		cnt1 = cnt1+1'b1;
end
//计数输入模式

reg [7:0] cnt8b;
reg i,j;
assign original_in = {1'b0,cnt8b};
always@(posedge key2 or negedge rstn)begin
	if(!rstn)
		i <= 0;
	else 
		i = 1;
end
always@(posedge key3 or negedge rstn)begin
	if(!rstn)
		j <= 0;
	else 
		j = 1;
end
always@(i or j)begin
	if(!rstn)
		cnt8b <= 0;
	else begin 
		if(i) cnt8b <= cnt8b + 1'b1;
		else if(j) cnt8b <= cnt8b - 1'b1;
		else;
	end	end Endmodule

//消抖模块 
module xiaodou(CLK,KEY_IN,RSTN,KEY); 
input CLK,KEY_IN,RSTN; 
output KEY; wire CLK,KEY_IN; 
reg KEY; reg[11:0] cnt4000; //可能有按键按下,开始计数 
always@(posedge CLK or negedge RSTN) 
if(!RSTN) cnt4000<=0; 
else begin 
if(!KEY_IN) 
if(cnt4000==4000) 
cnt4000<=0; 
else cnt4000<=cnt4000+1'b1; //理论 20ms 消抖时间 
else cnt4000<=0; //抖动时,计数会被清零 
end //产生消抖后的信号 
always@(posedge CLK or negedge RSTN) 
if(!RSTN) KEY<=1; 
else begin 
if(!KEY_IN) begin 
if(cnt4000==4000) KEY<=0; 
end 
else KEY<=1; 
end 
endmodule

附录II:设计约束脚本

#读入设计代码 
read_verilog {
encode_decode_top.v 
control_baud.v 
core_control.v 
decode_calculation.v 
running_disparity.v 
default_encode_3b_to_4b.v 
default_encode_5b_to_6b.v  
encode8b10b1.v  
encode_input_generate.v 
particular.v 
display2.v 
}
#约束设计指定
current_design encode_decode_top.v
#链接和检查 
Link  check_design
#时间、电阻、电容、电压、电流单位
set_units -time ns -resistance kOhm -capacitancepF-voltageV-current mA 
#工作环境
set_operating_conditions -max slow -max_library slow.db:slow
                         -min fast -min_library fast.db:fast
#线载模型指定
set_wire_load_model -name tsmc18_wl20 -library slow.db:slow
#设定输出网表的格式规则,以消除门级网表中的tri和assign
set verilogout_no_tri true
set_fix_multiple_port_nets -all -buffer_constants
#设定本地库 
set_local_link_library                                                          
{ /usr/eda/designKit/cic_tsmc18/synDC/slow.db, /usr/eda/designKit/cic_tsmc18/synDC/fast.db, 
/usr/eda/designKit/cic_tsmc18/synDC/tpz973gbc.db, 
/usr/eda/designKit/cic_tsmc18/synDC/tpz973gwc.db, 
/usr/eda/designKit/cic_tsmc18/synDC/tpz973gtc.db 
}
#检查时序 
check_timing
#设定时钟
create_clock [get_ports original_clk]  -period 20  -waveform {10 20}
set_clock_uncertainty -setup   0.3 [get_clocks original_clk] set_clock_latency -source -max 0.3 [get_clocks original_clk] set_clock_latency         -max 0.1 [get_clocks original_clk] set_clock_transition      -max 0.2 [get_clocks original_clk]
#避免在综合优化时对时钟或复位线上插入buffer
set_ideal_network [get_ports original_clk] 
set_ideal_network [get_ports rstn] set_dont_touch_network [get_clocks original_clk] set_dont_touch_network [get_ports rstn]
#输入延时
set_input_delay -clock original_clk  -max 7  [get_ports key1]
set_input_delay -clock original_clk  -max 7  [get_ports key2]
set_input_delay -clock original_clk  -max 7  [get_ports key3] 
#输出延时
set_output_delay -clock original_clk  -max 7 [get_ports {led_sel[5]}]
set_output_delay -clock original_clk  -max 7 [get_ports {led_sel[4]}]
set_output_delay -clock original_clk  -max 7 [get_ports {led_sel[3]}] set_output_delay -clock original_clk  -max 7 [get_ports {led_sel[2]}]
set_output_delay -clock original_clk  -max 7 [get_ports {led_sel[1]}]
set_output_delay -clock original_clk  -max 7 [get_ports {led_sel[0]}]
set_output_delay -clock original_clk  -max 7 [get_ports {led_drv[7]}]
set_output_delay -clock original_clk  -max 7 [get_ports {led_drv[6]}]
set_output_delay -clock original_clk  -max 7 [get_ports {led_drv[5]}]
set_output_delay -clock original_clk  -max 7 [get_ports {led_drv[4]}]
set_output_delay -clock original_clk  -max 7 [get_ports {led_drv[3]}] set_output_delay -clock original_clk  -max 7 [get_ports {led_drv[2]}] set_output_delay -clock original_clk  -max 7 [get_ports {led_drv[1]}]
set_output_delay -clock original_clk  -max 7 [get_ports {led_drv[0]}]
#设定最大扇出 
set_max_fanout 20 [current_design] 
#设定最大渡越时间 
set_max_transition 2 [current_design] 
#指定单元库模型 
set_driving_cell -lib_cell PDIDGZ -library tpz973gwc [get_ports key1] 
set_driving_cell -lib_cell PDIDGZ -library tpz973gwc [get_ports key2] set_driving_cell -lib_cell PDIDGZ -library tpz973gwc [get_ports key3]
#输出负载电容
set_load -pin_load 3 [get_ports {led_sel[5]}]
set_load -pin_load 3 [get_ports {led_sel[4]}]
set_load -pin_load 3 [get_ports {led_sel[3]}]
set_load -pin_load 3 [get_ports {led_sel[2]}]
set_load -pin_load 3 [get_ports {led_sel[1]}]
set_load -pin_load 3 [get_ports {led_sel[0]}]
set_load -pin_load 3 [get_ports {led_drv[7]}]
set_load -pin_load 3 [get_ports {led_drv[6]}]
set_load -pin_load 3 [get_ports {led_drv[5]}]
set_load -pin_load 3 [get_ports {led_drv[4]}]
set_load -pin_load 3 [get_ports {led_drv[3]}]
set_load -pin_load 3 [get_ports {led_drv[2]}]
set_load -pin_load 3 [get_ports {led_drv[1]}]
set_load -pin_load 3 [get_ports {led_drv[0]}]
#编译模式 
compile -map high  
#输出时序报告
rc > log/rc.log
#输出网表
write -f verilog -hier -o encode_decode.v
#输出综合数据文件
write -f ddc     -hier -o encode_decode.ddc
#输出延时文件
write_sdf  encode_decode.sdf
1

附录III:.synopsys_dc.setup文件

set company "SYLU" set designer "student" 
set libPath "/usr/eda/designKit/UMCArtisan18/aci" 
set search_path  "
/home/victor/dclab/rtl/code 
/home/victor/dclab/constraints 
$libPath/sc-x/synopsys 
$libPath/io/synopsys 
/usr/eda/libraries/syn 
/usr/synopsys/dc2016/dw/sim_ver 
/usr/synopsys/dc2016/dw/syn_ver 
                "    
set link_library  "
/usr/eda/designKit/cic_tsmc18/synDC/slow.db 
/usr/eda/designKit/cic_tsmc18/synDC/fast.db 
/usr/eda/designKit/cic_tsmc18/synDC/tpz973gbc.db
/usr/eda/designKit/cic_tsmc18/synDC/tpz973gwc.db
/usr/eda/designKit/synopsys/libraries/syn/dw_foundation.sldb
               "
set target_library "
/usr/eda/designKit/UMCArtisan18/aci/sc-x/synopsys/slow.db
/usr/eda/designKit/UMCArtisan18/aci/sc-x/synopsys/fast.db                   /usr/eda/designKit/UMCArtisan18/aci/io/synopsys/umc18io3v5v_slow.db                    /usr/eda/designKit/UMCArtisan18/aci/io/synopsys/umc18io3v5v_fast.db
               " 

set edifout_netlist_only "TRUE" set verilogout_no_tri true 
 set bus_inference_style {%s[%d]} set bus_naming_style {%s[%d]} set hdlout_internal_busses true #change_names -hierarchy -rule verilog 
define_name_rules name_rule -allowed {a-z A-Z 0-9 _} -max_length 255 
-type cell 
define_name_rules name_rule -allowed {a-z A-Z 0-9 _[]} -max_length 255 
-type net 
define_name_rules name_rule -map {{"\*cell\*" "cell"}} alias rc "report_timing"
原文地址:https://www.cnblogs.com/victorfengming/p/11931017.html