分类 🗜️IC&系统 下的文章 - 我的学记|刘航宇的博客
首页
📊归档
⏳时光机
📬留言
🐾友链
资助名单
推荐
🎓843课程班
🎵音乐
🏞️壁纸
搜 索
1
【NPN/PNP三极管】放大电路饱和失真和截止失真的区别
12,719 阅读
2
论文写作中如何把word里面所有数字和字母替换为新罗马字体
7,158 阅读
3
【高数】形心计算公式讲解大全
6,644 阅读
4
【1】基于STM32CubeMX-STM32GPIO端口开发
5,158 阅读
5
如何判断运放是工作在线性区还是非线性区
4,997 阅读
🌻微语&随笔
励志美文
我的随笔
写作办公
📖电子&通信
嵌入式&系统
通信&信息处理
编程&脚本笔记
🗜️IC&系统
FPGA&ASIC
VLSI&IC验证
EDA&虚拟机
💻电子&计算机
IP&SOC设计
机器学习
软硬件算法
登录
搜 索
标签搜索
嵌入式
ASIC/FPGA
VLSI
SOC设计
机器学习
天线设计
C/C++
EDA&虚拟机
软件算法
小实验
信号处理
电子线路
通信&射频
随笔
笔试面试
硬件算法
Verilog
软件无线电
Python
DL/ML
刘航宇
嵌入式系统&数字IC爱好者博客
累计撰写
302
篇文章
累计收到
527
条评论
首页
栏目
🌻微语&随笔
励志美文
我的随笔
写作办公
📖电子&通信
嵌入式&系统
通信&信息处理
编程&脚本笔记
🗜️IC&系统
FPGA&ASIC
VLSI&IC验证
EDA&虚拟机
💻电子&计算机
IP&SOC设计
机器学习
软硬件算法
页面
📊归档
⏳时光机
📬留言
🐾友链
资助名单
推荐
🎓843课程班
🎵音乐
🏞️壁纸
用户登录
登录
🗜️IC&系统(共77篇)
找到
77
篇与
🗜️IC&系统
相关的结果
【Verilog】卡诺图到电路Karnaugh Map to Circuit
问题描述一具有四个输入 (a,b,c,d) 的单输出数字系统在输入出现 2、7 或 15 时产生逻辑 1,当输入出现 0、1、4、5、6、9、10、13或14 时产生逻辑 0 。数字 3、8、11 和 12 的输入条件从未出现在此系统中。例如,7 对应于分别设置a,b,c,d为0、1、1、1。确定最小SOP形式的输出out_sop,以及最小POS形式的输出out_pos。问题解答(1)根据题意可以画出如下卡诺图: (2)随后进行卡诺图的化简:最小SOP:采用圈1法,如图中蓝色和绿色实线所示,合并标1的最小项,即。最小POS:采用圈0法,如图中红、黄、深蓝色虚线所示,合并标0的最小项,得到$L=c d+\bar \bar c$通过将该逻辑表达式进行化简,可以得到。$L=c \cdot(\bar+\bar+d) \cdot(\bar+\bar+d)$得到该卡诺图的逻辑表达式后,便可以开始编写verilog代码。module top_module ( input a, input b, input c, input d, output out_sop, output out_pos ); assign out_sop = (c&d)|(~a&~b&c); //sop assign out_pos = c&(~b|~c|d)&(~a|~c|d); //pos endmodule问题描述二得出下面卡诺图中显示的函数 f。 问题解答采用圈0法,如下图所示。 合并标0的最小项,得到$\bar=\overline} \overline}+\overline} \overline}+x_ \overline}+x_ x_$将该表达式化简,可以得到:$L=\left(x_+x_\right) \cdot\left(x_+x_\right) \cdot\left(\bar_ +x_\right) \cdot\left(\bar_+\bar_\right)$得到该卡诺图的逻辑表达式后,便可以开始编写verilog代码。module top_module ( input [4:1] x, output f ); assign f = (x[1]|x[3])&(x[3]|x[4])&(~x[1]|x[2])&(~x[1]|~x[3]); endmodule问题描述三得出下面卡诺图中显示的函数 f。(原试题要求简化 SOP 和 POS 形式的函数。) 问题解答最小SOP:采用圈1法,如下图所示。 合并标1的最小项,得到$L=\overline} \overline}+\bar_ x_+x_ x_ x_$最小POS:采用圈0法,如下图所示。 合并标0的最小项,得到$\bar=\overline} \overline}+x_ \overline}+x_ x_ \overline}+x_ \overline} x_$,通过化简该逻辑表达式,可以得到:$L=\left(x_+\overline}\right) \cdot\left(\overline}+x_\right) \cdot\left(\overline}+\overline}+x_\right) \cdot\left(\overline}+x_+\overline}\right)$得到该卡诺图的逻辑表达式后,便可以开始编写verilog代码。module top_module ( input [4:1] x, output f ); //assign f = (~x[2]&~x[4])|(~x[1]&x[3])|(x[2]&x[3]&x[4]); //sop assign f = (x[3]|~x[4])&(~x[2]|x[3])&(~x[1]|~x[2]|x[4])&(~x[1]|x[2]|~x[4]); //pos endmodule
2022年07月11日
498 阅读
0 评论
1 点赞
2022-07-06
【IC设计】数字IC设计流程及学习指南
IC的设计过程可分为两个部分,前端设计(也称逻辑设计)和后端设计(也称物理设计)并没有统一严格的界限,涉及到与工艺有关的设计就是后端设计。数字IC设计流程1. 规格制定芯片规格,也就像功能列表一样,是客户向芯片设计公司(称为Fabless,无晶圆设计公司)提出的设计要求,包括芯片需要达到的具体功能和性能方面的要求。2. 详细设计Fabless根据客户提出的规格要求,拿出设计解决方案和具体实现架构,划分模块功能。目前架构的验证一般基于SystemC语言,对构架模型的仿真可以使用SystemC的仿真工具。其中典型的例子是Synopsys公司的CoCentric和Summit公司的Visual Elite等。3. HDL编码使用硬件描述语言(VHDL,Verilog HDL,业界公司一般都是使用后者)将模块功能以代码来描述实现,也就是将实际的硬件电路功能通过HDL语言描述出来,形成RTL(寄存器传输级)代码。设计输入工具:具有强大的文本编辑功能,多种输入方法(VHDL,Verilog,状态转移图,模块图等),语法模板,语法检查,自动生产代码和文档等功能。如Active-HDL,VisualVHDL/Verilog等。RTL分析检查工具:Synopsys LEDA4. 仿真验证仿真验证就是检验编码设计的正确性,检验的标准就是第一步制定的规格。看设计是否精确地满足了规格中的所有要求。规格是设计正确与否的黄金标准,一切违反,不符合规格要求的,就需要重新修改设计和编码。设计和仿真验证是反复迭代的过程,直到验证结果显示完全符合规格标准。仿真验证工具Synopsys的VCS,Mentor ModelSim,Cadence Verilog-XL,Cadence NC-Verilog。5. 逻辑综合――Design Compiler仿真验证通过,进行逻辑综合。逻辑综合的结果就是把设计实现的HDL代码翻译成门级网表netlist。综合需要设定约束条件,就是你希望综合出来的电路在面积,时序等目标参数上达到的标准。逻辑综合需要基于特定的综合库,不同的库中,门电路基本标准单元(standard cell)的面积,时序参数是不一样的。所以,选用的综合库不一样,综合出来的电路在时序,面积上是有差异的。一般来说,综合完成后需要再次做仿真验证(这个也称为后仿真,之前的称为前仿真)逻辑综合工具Synopsys的Design Compiler(DC),Cadence的 PKS,Synplicity的Synplify等。另外,和综合工具配合使用的还有很多其他工具,如静态时间分析工具,等效性检查工具等等。Synopsys公司和Cadence公司都提供完整的工具包。5.1. STAStatic Timing Analysis(STA),静态时序分析,这也属于验证范畴,它主要是在时序上对电路进行验证,检查电路是否存在建立时间(setup time)和保持时间(hold time)的违例(violation)。这个是数字电路基础知识,一个寄存器出现这两个时序违例时,是没有办法正确采样数据和输出数据的,所以以寄存器为基础的数字芯片功能肯定会出现问题。STA工具有Synopsys的Prime Time。5.2. 形式验证这也是验证范畴,它是从功能上(STA是时序上)对综合后的网表进行验证。常用的就是等价性检查(Equivalence Check)方法,以功能验证后的HDL设计为参考,对比综合后的网表功能,他们是否在功能上存在等价性。这样做是为了保证在逻辑综合过程中没有改变原先HDL描述的电路功能。形式验证工具有Synopsys的Formality。前端设计的流程暂时写到这里。从设计程度上来讲,前端设计的结果就是得到了芯片的门级网表电路。技能图解1.语言主流的Verilog、VHDLVerilog语言与软件语言最大的区别就是,因为它是用于描述电路的,因此它的写法是非常固定的,因为电路的变化是非常有限的。学习Verilog的时候,很多时候我们并不是在学习这门语言本身,而是学习其对应的电路特征,以及如何对这个电路进行描述。如果心中没有电路,那么你是不可能写好Verilog的。VHDL语言的严谨性比Verilog要好,不像Verilog中一样存在大量符合语法却永远无法综合的语句。SpinalHDL、Myhdl等SpinalHDL和Chisel师承一脉,都是基于Scala来进行电路描述。其本质上仍旧是HDL而非HLS,在设计之前依旧需要有清晰的电路结构,只不过是在电路描述上更加方便和快捷而已。目前有一些公司已经应用于FPGA设计中,ASIC应用还有待探究。SpinalHDL资料:https://spinalhdl.github.io/SpinalDoc-RTD/master/index.htmlSystemVerilog/SystemC :这两种语言都是为了验证而存在的,掌握基本的验证方法学有助于提高自己的debug效率,SystemVerilog是一种面向对象的语言,其设计的本意是用于搭建验证平台,主流的UVM方法也都是基于SystemVerilog实现的,所以立志成为IC验证工程师的同学,SystemVerilog的深入学习和流行方法论的学习都是必不可少的。而对于那些只想做IC设计的同学而言,SystemVerilog同样也是值得学习的。且不说本文前面提到的用于提高验证效率的debug方法,即使只是为了做好设计,SystemVerilog也是大有用武之地。很多顶级的IC设计公司内部都开始使用SystemVerilog进行RTL设计了。由于在SystemVerilog中加入了很多类似always_ff、always_comb等用于显式表明综合电路意图的新语法,代码的可读性更高,综合过程中也减少了歧义,尽可能地保证了综合结果与设计意图的一致性。从另一个角度来说,assertion的加入也极大地提高了代码的debug效率,非常有助于在大规模的数据交互过程中定位到出错的初始点,没有掌握的同学可以多花一些时间学习一下。-> SV基础知识脚本语言:Makefile/Perl/Python/ShellMakefile/Perl/Python/Shell都是常用的脚本语言,进行批量修改文本内容,实现自动化操作等,掌握一门得心应手的脚本语言将对工作效率的提升帮助极大。但凡做过一次的事情,就没有必要重复第二次。-> Perl在IC中的应用脚本语言:Tcl在IC设计这个领域中,Tcl是一门非常常见的语言。可以用于描述时序和管脚约束文件,UPF信息,也可以用来搭建简单的工作平台。既是很多EDA工具默认支持的脚本语言,也是这些工具配置和输出的文件格式。因此,能够读懂Tcl,掌握Tcl语言的基本语法,就可以帮助更好的使用EDA工具。-> 从零开始学TclC语言作为基础语言,在验证时,往往需要用到C写的case;2.基础知识数电模电、电路分析、数据结构、计算机体系架构等AMBA总线AXI、AHB、APB、CHI、ACE等;-> AMBA总线高低速接口PCIE、DMA、DDR、USB、UART、SPI、I2C、MIPI等-> 总线接口低功耗设计动态功耗、静态功耗、常见低功耗设计方法-> 低功耗设计静态时序分析建立时间、保持时间、亚稳态及其解决方法、时序约束-> 时序约束策略 、亚稳态、 FPGA中的亚稳态设计方法乒乓操作、流水线、串并转换、无毛刺切换、状态机等跨时钟处理:快到慢、慢到快、异步FIFO(FIFO深度计算)等->时钟切换电路(Glitch-free clock switching circuit)、异步FIFO、同步FIFO、同步和异步FIFO、FIFO深度计算3.设计工具linux系统:linux、shell常见命令gvim/emac编辑器:熟练使用Vim/Emacs,用编程的方式来编程,可以提高效率。版本管理工具:SVN、Git、p4等版本管理,简而言之,就是一种用于记录和查询文件版本改动的工具;EDA工具仿真工具:NCVerilog/ VCS/ ModelSim/ iVerilog以上是比较业界比较主流的仿真工具,其中Icarus Verilog (iVerilog)为开源工具,仿真过程需要了解:如何指定编译的文件类型;如何指定编译文件清单;如何指定索引目录;如何指定仿真精度;如何指定临时的宏变量;如何指定语法检查的严苛等级;如何混合编译由多种语言写成的工程;如何调用不同波形生成工具的pli接口;如何配合SDF反标进行后仿等;-> 芯片后仿及SDF反标、VCS实用技巧、开源verilog仿真工具iverilog+GTKWave波形查看工具:DVE/ Verdi/ gtkWave以上是业界比较主流的波形查看工具,所有的波形查看器都必须支持标准波形文件.vcd格式,但是由于.vcd格式的存储性能并不好,冗余信息过多,所以各波形查看工具都纷纷推出了自己支持的波形文件格式,如DVE的.vpd,Verdi的.fsdb,ModelSim的*.wlf;gtkWave也是跨平台的,而且简单易用,支持.vcd标准格式,同时支持高性能压缩格式.lxt和*.fst,gtkWave自带vcd转fst的转换器;通常几G左右的.vcd格式波形转换为.vpd格式后只有几十MB左右,而转换为.fsdb后通常会更小,因此将标准波形文件.vcd转换为其他压缩格式更加有利于数据备份。-> fsdb实用技巧、verdi实用技巧逻辑等效性检查工具:formality-> 形式验证与formality基本流程从功能上对综合后的网表进行验证,常用的就是等价性检查方法,以功能验证后的HDL设计为参考,对比综合后的网表功能,他们是否在功能上存在等价性。这样做是为了保证在逻辑综合过程中没有改变原先HDL描述的电路功能。综合工具:dc ->DC综合逻辑综合就是将HDL代码翻译成门级网表netlist;lint/cdc检查工具:spyglass -> SpyGlass安装教程、spyglass 基础操作、spyglass 常见错误lint后端:PT、IIC2、innovus等FPGA综合布线布局工具:synplify/vivado->->synplify 基础操作、基于synplify+vivado生成bitfile其他:VC_static_tools ->VC_static Tools安装教程4.相关岗位前端设计RTL IP设计:从算法协议到RTL coding的能力;SoC设计集成/验证:总线、功耗、系统架构的能力;SOC侧重将IP,模块集成形成一个系统,所以片上互联总线和外设接口是掌握的重点。片内互联总线一般是AMBA总线。外设接口又分为低速接口和高速接口,其中低速接口包括I2C,UART,SPI等,高速接口包括SATA,USB,PCIE,DDR等;验证FPGA原型验证:HAPS -> HAPS®-100原型系统、芯片验证技术 |HAPS与高性能ASIC原型验证UVM验证:SV、UVM主流验证方法学 ->UVM芯片验证EMU验证:zebu、帕拉丁 -> 芯片验证应用|基于ZeBu平台的虚拟主机应用方案综合:逻辑综合就是将HDL代码翻译成门级网表netlist;STAStatic Timing Analysis(STA),静态时序分析,它主要是在时序上对电路进行验证,检查电路是否存在建立时间(setup time)和保持时间(hold time)的违例(violation),一个寄存器出现这两个时序违例时,是没有办法正确采样数据和输出数据的,所以以寄存器为基础的数字芯片功能肯定会出现问题。DFTDesign ForTest,可测性设计。芯片内部往往都自带测试电路,DFT的目的就是在设计的时候就考虑将来的测试。DFT的常见方法就是,在设计中插入扫描链,将非扫描单元(如寄存器)变为扫描单元;如bist、Scan Design、JTAG、ATPG等;后端物理验证、布线布局、静态时序分析、等价性检查、功耗分析
2022年07月06日
1,507 阅读
0 评论
9 点赞
【9】Verilog练习-串口指令处理器
理论: 代码cmd_pro//指令处理器 `timescale 1ns/10ps module cmd_pro( clk, res, din_pro, en_din_pro, dout_pro, en_dout_pro, rdy ); input clk; input res; input[7:0] din_pro;//指令和数据输入端口; input en_din_pro;//输入使能; output[7:0] dout_pro;//指令执行结果; output en_dout_pro;//指令输出使能; output rdy;//串口发送模块空闲标志,0表示空闲; parameter add_ab=8'h0a; parameter sub_ab=8'h0b; parameter and_ab=8'h0c; parameter or_ab=8'h0d; reg[2:0] state;//主状态机寄存器(2^3个状态); reg[7:0] cmd_reg,A_reg,B_reg;//存放指令、A和B; reg[7:0] dout_pro; reg en_dout_pro; always@(posedge clk or negedge res) if(~res)begin state<=0;cmd_reg<=0;A_reg<=0;B_reg<=0;dout_pro<=0; en_dout_pro<=0; end else begin case(state) 0://等指令; begin en_dout_pro<=0; if(en_din_pro) begin cmd_reg<=din_pro; state<=1; end end 1://收A; begin if(en_din_pro) begin A_reg<=din_pro; state<=2; end end 2://收B; begin if(en_din_pro) begin B_reg<=din_pro; state<=3; end end 3://指令译码和执行 begin state<=4; case(cmd_reg) add_ab: begin dout_pro<=A_reg+B_reg; end sub_ab: begin dout_pro<=A_reg-B_reg; end and_ab: begin dout_pro<=A_reg&B_reg; end or_ab: begin dout_pro<=A_reg|B_reg; end endcase end 4://发送指令执行结果 begin if(~rdy)begin en_dout_pro<=1; state<=0; end end default:// begin state<=0; en_dout_pro<=0; end endcase end endmoduleUART_top//串口指令处理器 `timescale 1ns/10ps module UART_top( clk, res, RX, TX ); input clk; input res; input RX; output TX; wire[7:0] din_pro; wire en_din_pro; wire[7:0] dout_pro; wire en_dout_pro; wire rdy; UART_Rxer UART_Rxer( .clk(clk), .res(res), .RX(RX), .data_out(din_pro), .en_data_out(en_din_pro) ); UART_TXer UART_TXer( .clk(clk), .res(res), .data_in(dout_pro), .en_data_in(en_dout_pro), .TX(TX), .rdy(rdy) ); cmd_pro cmd_pro( .clk(clk), .res(res), .din_pro(din_pro), .en_din_pro(en_din_pro), .dout_pro(dout_pro), .en_dout_pro(en_dout_pro), .rdy(rdy) ); endmodule //-----testbench of UART_top----- module UART_top_tb; reg clk,res; wire RX; wire TX; reg[45:0] RX_send;//里面装有串口字节发送数据 assign RX=RX_send[0];//连接RX; reg[12:0] con; UART_top UART_top( clk, res, RX, TX ); initial begin clk<=0;res<=0;RX_send<=; con<=0; #17 res<=1; #4000000 $stop; end always #5 clk<=~clk; always@(posedge clk)begin if(con==5000-1)begin con<=0; end else begin con<=con+1; end if(con==0)begin RX_send[44:0]<=RX_send[45:1]; RX_send[45]<=RX_send[0]; end end endmodule现象
2022年06月23日
212 阅读
0 评论
2 点赞
2022-06-21
【8】Verilog练习-串口数据发送
理论: 代码://串口发送模块 `timescale 1ns/10ps module UART_TXer( clk, res, data_in, en_data_in, TX, rdy ); input clk; input res; input[7:0] data_in;//准备发送的数据; input en_data_in;//发送使能; output TX;//输出使能 output rdy;//空闲标志,0表示空闲; reg[3:0] state;//主状态机寄存器; reg[9:0] send_buf;//发送寄存器 assign TX=send_buf[0];//连接TX; reg[9:0] send_flag;//用于判断右移结束; reg[12:0] con;//用于计算波特周期 reg rdy; always@(posedge clk or negedge res) if(~res)begin state<=0;send_buf<=1;con<=0;send_flag<=10'b10_0000_0000;rdy<=0; end else begin case(state) 0://等待使能信号; begin if(en_data_in)begin send_buf=; send_flag<=10'b10_0000_0000; rdy<=1; state<=1; end end 1://串口发送,寄存器右移; begin if(con==5000-1)begin con<=0; end else begin con<=con+1; end if(con==5000-1)begin send_buf[8:0]<=send_buf[9:1]; send_flag[8:0]<=send_flag[9:1]; end if(send_flag[0])begin rdy<=0; state<=0; end end endcase end endmodule //----testbench of UART_TXer--- module UART_TXer_tb; reg clk,res; reg[7:0] data_in; reg en_data_in; wire TX; wire rdy; UART_TXer UART_TXer( //同名例化; clk, res, data_in, en_data_in, TX, rdy ); initial begin clk<=0;res<=0;data_in<=8'h7f;en_data_in<=0; #17 res<=1; #30 en_data_in<=1; #10 en_data_in<=0; #10000 $stop; end always #5 clk<=~clk; endmodule结果:
2022年06月21日
231 阅读
0 评论
3 点赞
2022-06-15
【7】Verilog练习-串口数据接收
原理:程序//串口数据接收 `timescale 1ns/10ps module UART_Rxer( clk, res, RX, data_out, en_data_out ); input clk; input res; input RX; output[7:0] data_out;//接收字节输出; output en_data_out;//输出使能; reg[7:0] data_out; reg[7:0] state;//主状态机; reg[12:0] con;//用于计算比特宽度; reg[3:0] con_bits;//用于计算比特数; reg RX_delay;//RX的延时; reg en_data_out; always@(posedge clk or negedge res) if(~res)begin state<=0;con<=0;con_bits<=0;RX_delay<=0; data_out<=0;en_data_out<=0; end else begin RX_delay<=RX; case(state) 0://等空闲; begin if(con==5000-1)begin //24M/4800=5000 con<=0; end else begin con<=con+1; end if(con==0)begin if(RX)begin con_bits<=con_bits+1; end else begin con_bits<=0; end if(con_bits==12)begin//连续12个1,说明处于空闲状态 state<=1; end end end 1://等起始位; begin en_data_out<=0; if(~RX&RX_delay)begin state<=2; end end 2://收最低位b0;T=5000;1.5T=7500 begin if(con==7500-1)begin con<=0; data_out[0]<=RX; state<=3; end else begin con<=con+1; end end 3://收最低位b1; begin if(con==5000-1)begin con<=0; data_out[1]<=RX; state<=4; end else begin con<=con+1; end end 4://收最低位b2; begin if(con==5000-1)begin con<=0; data_out[2]<=RX; state<=5; end else begin con<=con+1; end end 5://收最低位b3; begin if(con==5000-1)begin con<=0; data_out[3]<=RX; state<=6; end else begin con<=con+1; end end 6://收最低位b4; begin if(con==5000-1)begin con<=0; data_out[4]<=RX; state<=7; end else begin con<=con+1; end end 7://收最低位b5; begin if(con==5000-1)begin con<=0; data_out[5]<=RX; state<=8; end else begin con<=con+1; end end 8://收最低位b6; begin if(con==5000-1)begin con<=0; data_out[6]<=RX; state<=9; end else begin con<=con+1; end end 9://收最低位b7; begin if(con==5000-1)begin con<=0; data_out[7]<=RX; state<=10; end else begin con<=con+1; end end 10://产生使能脉冲 begin en_data_out<=1; state<=1; end default:// begin state<=0; con<=0; con_bits<=0; en_data_out<=0; end endcase end endmodule //----testbench of UART_Rxer-- module UART_Rxer_tb; reg clk,res; wire RX; wire[7:0] data_out; wire en_data_out; reg[25:0] RX_send;//里面装有串口字节发送数据; assign RX=RX_send[0];//连接RX reg[12:0] con; UART_Rxer UART_Rxer( .clk(clk), .res(res), .RX(RX), .data_out(data_out), .en_data_out(en_data_out) ); initial begin clk<=0;res<=0;RX_send<=; con<=0; #17 res<=1; #4000000 $stop; end always #5 clk<=~clk; always@(posedge clk)begin if(con==5000-1)begin con<=0; end else begin con<=con+1; end if(con==0)begin RX_send[24:0]<=RX_send[25:1]; RX_send[25]<=RX_send[0]; end end endmodule现象
2022年06月15日
263 阅读
0 评论
3 点赞
【6】Verilog练习-三角波梯形波发生器
三角波发生器理论代码//三角波发生器 `timescale 1ns/10ps module tri_gen( clk, res, d_out ); input clk; input res; output[8:0] d_out; reg state; reg[8:0] d_out; always@(posedge clk or negedge res) if(~res) begin state<=0;d_out<=0; end else begin case(state) 0://上升 begin d_out<=d_out+1; if(d_out==299)begin state<=1; end end 1://下降 begin d_out<=d_out-1; if(d_out==1)begin state<=0; end end endcase end endmodule //------testbench of tri_gen---- module tri_gen_tb; reg clk,res; wire[8:0] d_out; tri_gen U1( .clk(clk), .res(res), .d_out(d_out) ); initial begin clk<=0;res<=0; #17 res<=1; #8000 $stop; end always #5 clk<=~clk; endmodule现象梯形波发生器//三角波发生器->改进为梯形波 `timescale 1ns/10ps module tri_gen( clk, res, d_out ); input clk; input res; output[8:0] d_out; reg[1:0] state;//3个状态2位,不在是原来的1bit reg[8:0] d_out; reg[7:0] con;//计数器,记录平顶周期个数 always@(posedge clk or negedge res) if(~res) begin state<=0;d_out<=0;con<=0; end else begin case(state) 0://上升 begin d_out<=d_out+1; if(d_out==299)begin state<=1; end end 1://平顶 begin if(con==200) begin state<=2; con<=0; end else begin con<=con+1; end end 2://下降 begin d_out<=d_out-1; if(d_out==1)begin state<=0; end end default://3状态 begin state<=0; con<=0; end endcase end endmodule //------testbench of tri_gen---- module tri_gen_tb; reg clk,res; wire[8:0] d_out; tri_gen U1( .clk(clk), .res(res), .d_out(d_out) ); initial begin clk<=0;res<=0; #17 res<=1; #20000 $stop; end always #5 clk<=~clk; endmodule现象
2022年06月02日
477 阅读
0 评论
3 点赞
2022-05-25
【5】Verilog练习-相邻16点相加
代码//相邻16点相加 `timescale 1ns/10ps module sigma_16p( clk, res, data_in, syn_in, data_out, syn_out ); input clk,res; input[7:0] data_in;//采样信号 input syn_in;//采样时钟 output[11:0] data_out;//累加结果输出 output syn_out;//累加结果同步脉冲 reg syn_in_n1;//syn_in的反向延时 wire syn_pulse;//采样时钟上升沿识别脉冲 assign syn_pulse=syn_in&syn_in_n1; reg[3:0] con_syn;//采样时钟循环计数器 wire[7:0] comp_8;//补码 wire[11:0] d_12;//升位结果 assign comp_8=data_in[7]?:data_in;//补码运算 assign d_12=; reg[11:0] sigma;//累加计算 reg[11:0] data_out; reg syn_out; always@(posedge clk or negedge res) if(~res)begin syn_in_n1<=0;con_syn<=0;sigma<=0;data_out<=0;syn_out<=0; end else begin syn_in_n1<=~syn_in; if(syn_pulse)begin con_syn<=con_syn+1; end if(syn_pulse)begin if(con_syn==15)begin sigma<=d_12; data_out<=sigma; syn_out<=1; end else begin sigma<=sigma+d_12; end end else begin syn_out<=0; end end endmodule //-----testbench of sigma_16p--- module sigma_16p_tb; reg clk,res; reg[7:0] data_in; reg syn_in; wire[11:0] data_out; wire syn_out; sigma_16p sigma_16p( .clk(clk), .res(res), .data_in(data_in), .syn_in(syn_in), .data_out(data_out), .syn_out(syn_out) ); initial begin clk<=0;res<=0;data_in=1;syn_in<=0; #17 res<=1; #50000 $stop; end always #5 clk<=~clk; always #100 syn_in<=~syn_in; endmodule现象
2022年05月25日
239 阅读
0 评论
1 点赞
【4】Verilog练习-秒计数器设计
秒计数器设计代码//秒计数器,0-9循环 `timescale 1ns/10ps module s_counter( clk, res, s_num ); input clk; input res; output[3:0] s_num; parameter frequency_clk=24;//24MHZ; reg[24:0] con_t;//秒脉冲分频计数器; reg s_pulse;//秒脉冲尖; reg[3:0] s_num; always@(posedge clk or negedge res) if(~res)begin con_t<=0;s_pulse<=0;s_num<=0; end else begin //if(con_t==frequency_clk*1000000-1)begin if(con_t==frequency_clk*1000-1)begin//仿真便于观察 con_t<=0; end else begin con_t<=con_t+1; end if(con_t==0)begin s_pulse<=1; end else begin s_pulse<=0; end if(s_pulse) begin if(s_num==9)begin s_num<=0; end else begin s_num<=s_num+1; end end end endmodule //-----testbench of s_counter--- module s_counter_tb; reg clk,res; wire[3:0] s_num; s_counter s_counter( .clk(clk), .res(res), .s_num(s_num) ); initial begin clk<=0;res<=0; #17 res<=1; #1000000 $stop; end always #5 clk<=~clk; endmodule现象扩展:数码管
2022年05月24日
212 阅读
0 评论
2 点赞
2022-05-23
【3】Verilog练习-时序逻辑与伪随机码发生器设计和仿真
时序逻辑代码与仿真代码//计数器 `timescale 1ns/10ps module counter( clk, res, y ); input clk; input res; output[7:0] y; reg[7:0] y; wire[7:0] sum;//+1运算的结果; assign sum=y+1;//组合逻辑部分; always@(posedge clk or negedge res) if(~res)begin y<=0; end else begin y<=sum; end endmodule //----testbench of counter---- module counter_tb; reg clk,res; wire[7:0] y; counter counter( .clk(clk), .res(res), .y(y) ); initial begin clk<=0;res<=0; #17 res<=1; #6000 $stop; end always #5 clk<=~clk; endmodule现象模拟显示伪随机码发生器代码//四级伪随机码发生器; `timescale 1ns/10ps module m_gen( clk, res, y ); input clk; input res; output y; reg[3:0] d; assign y=d[0]; always@(posedge clk or negedge res) if(~res)begin d<=4'b1111; end else begin d[2:0]<=d[3:1];//右移一位; d[3]<=d[3]+d[0];//模二加; end endmodule //----testbench of m_gen---- module m_gen_tb; reg clk,res; wire y; m_gen m_gen( .clk(clk), .res(res), .y(y) ); initial begin clk<=0;res<=0; #17 res<=1; #600 $stop; end always #5 clk<=~clk; endmodule现象
2022年05月23日
251 阅读
0 评论
1 点赞
2022-05-21
【2】Verilog练习-补码转化与7段译码逻辑设计
补码转化程序//补码转化逻辑 `timescale 1ns/10ps module comp_conv( a, a_comp ); input[7:0] a; output[7:0] a_comp; //wire[6:0] b;//按位取反的幅度位 //wire[7:0] y;//负数的补码; //assign b=~a[6:0]; //assign y[6:0]=b+1;//按位取反+1 //assign y[6:0]=~a[6:0]+1;//按位取反+1 //assign y[7]=a[7];//符号位不变 //assign y=; //assign a_comp=a[7]?y:a;//二选一 assign a_comp=a[7]?:a;//二选一 endmodule //----testbench of comp_conv--- module comp_conv_tb; reg[7:0] a_in; wire[7:0] y_out; comp_conv comp_conv( .a(a_in), .a_comp(y_out) ); initial begin a_in<=0; #3000 $stop; end always #10 a_in<=a_in+1; endmodule现象7段译码逻辑设计代码://七段码译码器 `timescale 1ns/10ps module seg_dec( num, a_g ); input[3:0] num; output[6:0] a_g;//a_g--> reg[6:0] a_g; always@(num)begin case(num) 4'd0: begin a_g<=7'b111_1110; end 4'd1: begin a_g<=7'b011_0000; end 4'd2: begin a_g<=7'b110_1101; end 4'd3: begin a_g<=7'b111_1100; end 4'd4: begin a_g<=7'b011_0011; end 4'd5: begin a_g<=7'b101_1011; end 4'd6: begin a_g<=7'b101_1111; end 4'd7: begin a_g<=7'b111_0000; end 4'd8: begin a_g<=7'b111_1111; end 4'd9: begin a_g<=7'b111_1011; end default: begin a_g<=7'b000_0001; end//中杠 endcase end endmodule //----testbench of seg_dec--- module seg_dec_tb; reg[3:0] num_in; wire[6:0] a_g_out; seg_dec seg_dec( .num(num_in), .a_g(a_g_out) ); initial begin num_in<=0; #200 $stop; end always #10 num_in<=num_in+1; endmodule现象
2022年05月21日
382 阅读
0 评论
3 点赞
2022-05-17
【2】Verilog练习-组合逻辑电路多路选择器
二选一逻辑设计程序//二选一逻辑设计 `timescale 1ns/10ps module fn_sw( a, b, sel, y ); input a; input b; input sel; output y; //assign y=sel?(a^b):(a&b); //用always语句块实现组合逻辑; reg y; always@(a or b or sel) if(sel==1)begin y<=a^b; end else begin y<=a&b; end endmodule //---testbench of fn_sw---- module fn_sw_tb; reg a,b,sel;//输入reg型 wire y;//输出wire型 fn_sw fn_sw( .a(a), .b(b), .sel(sel), .y(y) ); initial begin a<=0;b<=0;sel<=0; #10 a<=0;b<=0;sel<=1; #10 a<=0;b<=1;sel<=0; #10 a<=1;b<=0;sel<=0; #10 a<=1;b<=0;sel<=1; #10 a<=1;b<=1;sel<=0; #10 a<=1;b<=1;sel<=1; #10 $stop; end endmodule现象多路选择逻辑设计代码//四选一逻辑设计 `timescale 1ns/10ps module fn_sw_4( a, b, sel, y ); input a; input b; input[1:0] sel; output y; reg y; always@(a or b or sel)begin case(sel) 2'b00:begin y<=a&b;end 2'b01:begin y<=a|b;end 2'b10:begin y<=a^b;end 2'b11:begin y<=~(a^b);end endcase end endmodule //-----testbench of fn_sw_4-- module fn_sw_4_tb; reg[3:0] absel; wire y; fn_sw_4 fn_sw_4( .a(absel[0]), .b(absel[1]), .sel(absel[3:2]), .y(y) ); initial begin absel<=0; #300 $stop; end always #10 absel<=absel+1; endmodule现象
2022年05月17日
373 阅读
0 评论
2 点赞
2022-05-16
【4】Verilog-基础语法2
表达式表达式由操作符和操作数构成,其目的是根据操作符的意义得到一个计算结果。表达式可以在出现数值的任何地方使用。例如:a^b ; //a与b进行异或操作 address[9:0] + 10'b1 ; //地址累加 flag1 && flag2 ; //逻辑与操作操作数 操作数可以是任意的数据类型,只是某些特定的语法结构要求使用特定类型的操作数。操作数可以为常数,整数,实数,线网,寄存器,时间,位选,域选,存储器及函数调用等。module test; //实数 real a, b, c; c = a + b ; //寄存器 reg [3:0] cprmu_1, cprmu_2 ; always @(posedge clk) begin cprmu_2 = cprmu_1 ^ cprmu_2 ; end //函数 reg flag1 ; flag = calculate_result(A, B); //非法操作数 reg [3:0] res; wire [3:0] temp; always@ (*)begin res = cprmu_2 – cprmu_1 ; //temp = cprmu_2 – cprmu_1 ; //不合法,always块里赋值对象不能是wire型 end endmodule操作符 Verilog 中提供了大约 9 种操作符,分别是算术、关系、等价、逻辑、按位、归约、移位、拼接、条件操作符。大部分操作符与 C 语言中类似。同类型操作符之间,除条件操作符从右往左关联,其余操作符都是自左向右关联。圆括号内表达式优先执行。例如下面每组的 2 种写法都是等价的。不同操作符之间,优先级是不同的。下表列出了操作符优先级从高至低的排列顺序。当没有圆括号时,Verilog 会根据操作符优先级对表达式进行计算。为了避免由操作符优先级导致的计算混乱,在不确定优先级时,建议用圆括号将表达式区分开来。 算术操作符 算术操作符包括单目操作符和双目操作符。双目操作符对 2 个操作数进行算术运算,包括乘()、除(/)、加(+)、减(-)、求幂(*)、取模(%)。reg [3:0] a, b; reg [4:0] c ; a = 4'b0010 ; b = 4'b1001 ; c = a+b; //结果为c=b'b1011 c = a/b; //结果为c=4,取整如果操作数某一位为 X,则计算结果也会全部出现 X。例如:b = 4'b100x ; c = a+b ; //结果为c=4'bxxxx对变量进行声明时,要根据变量的操作符对变量的位宽进行合理声明,不要让结果溢出。上述例子中,相加的 2 个变量位宽为 4bit,那么结果寄存器变量位宽最少为 5bit。否则,高位将被截断,导致结果高位丢失。无符号数乘法时,结果变量位宽应该为 2 个操作数位宽之和。reg [3:0] mula ; reg [1:0] mulb; reg [5:0] res ; mula = 4'he ; mulb = 2'h3 ; res = mula * mulb ; //结果为res=6'h2a, 数据结果没有丢失位数和 - 也可以作为单目操作符来使用,表示操作数的正负性。此类操作符优先级最高。-4 //表示负4+3 //表示正3负数表示时,可以直接在十进制数字前面增加一个减号 -,也可以指定位宽。因为负数使用二进制补码来表示,不指定位宽来表示负数,编译器在转换时,会自动分配位宽,从而导致意想不到的结果。例如:mula = -4'd4 ; mulb = 2 ; res = mula * mulb ; //计算结果为res=-6'd8, 即res=6'h38,正常 res = mula * (-'d4) ; //(4的32次幂-4) * 2, 结果异常关系操作符 关系操作符有大于(>),小于(<),大于等于(>=),小于等于(<=)。关系操作符的正常结果有 2 种,真(1)或假(0)。如果操作数中有一位为 x 或 z,则关系表达式的结果为 x。A = 4 ; B = 3 ; X = 3'b1xx ; A > B //为真 A <= B //为假 A >= Z //为X,不确定等价操作符 等价操作符包括逻辑相等(==),逻辑不等(!=),全等(===),非全等(!==)。等价操作符的正常结果有 2 种:为真(1)或假(0)。逻辑相等/不等操作符不能比较 x 或 z,当操作数包含一个 x 或 z,则结果为不确定值。全等比较时,如果按位比较有相同的 x 或 z,返回结果也可以为 1,即全等比较可比较 x 或 z。所以,全等比较的结果一定不包含 x。举例如下:A = 4 ; B = 8'h04 ; C = 4'bxxxx ; D = 4'hx ; A == B //为真 A == (B + 1) //为假 A == C //为X,不确定 A === C //为假,返回值为0 C === D //为真,返回值为1逻辑操作符 逻辑操作符主要有 3 个:&&(逻辑与), ||(逻辑或),!(逻辑非)。逻辑操作符的计算结果是一个 1bit 的值,0 表示假,1 表示真,x 表示不确定。如果一个操作数不为 0,它等价于逻辑 1;如果一个操作数等于 0,它等价于逻辑 0。如果它任意一位为 x 或 z,它等价于 x。如果任意一个操作数包含 x,逻辑操作符运算结果不一定为 x。逻辑操作符的操作数可以为变量,也可以为表达式。例如:A = 3; B = 0; C = 2'b1x ; A && B // 为假 A || B // 为真 ! A // 为假 ! B // 为真 A && C // 为X,不确定 A || C // 为真,因为A为真 (A==2) && (! B) //为真,此时第一个操作数为表达式按位操作符 按位操作符包括:取反(~),与(&),或(|),异或(^),同或(~^)。按位操作符对 2 个操作数的每 1bit 数据进行按位操作。如果 2 个操作数位宽不相等,则用 0 向左扩展补充较短的操作数。取反操作符只有一个操作数,它对操作数的每 1bit 数据进行取反操作。下图给出了按位操作符的逻辑规则。A = 4'b0101 ; B = 4'b1001 ; C = 4'bx010 ; ~A //4'b1010 A & B //4'b0001 A | B //4'b1101 A^B //4'b1100 A ~^ B //4'b0011 B | C //4'b1011 B&C //4'bx000移位操作符 移位操作符包括左移(<<),右移(>>),算术左移(<<<),算术右移(>>>)。移位操作符是双目操作符,两个操作数分别表示要进行移位的向量信号(操作符左侧)与移动的位数(操作符右侧)。算术左移和逻辑左移时,右边低位会补 0。逻辑右移时,左边高位会补 0;而算术右移时,左边高位会补充符号位,以保证数据缩小后值的正确性。A = 4'b1100 ; B = 4'b0010 ; A = A >> 2 ; //结果为 4'b0011 A = A << 1; //结果为 4'b1000 A = A <<< 1 ; //结果为 4'b1000 C = B + (A>>>2); //结果为 2 + (-4/4) = 1, 4'b0001拼接操作符 拼接操作符用大括号 来表示,用于将多个操作数(向量)拼接成新的操作数(向量),信号间用逗号隔开。拼接符操作数必须指定位宽,常数的话也需要指定位宽。例如:A = 4'b1010 ; B = 1'b1 ; Y1 = ; //结果为Y1='b1100_0011 Y2 = , 3'd4}; //结果为 Y2=7'b111_1100 Y3 = }; //结果为 Y3=32h0,常用作寄存器初始化时匹配位宽的赋初值条件操作符条件表达式有 3 个操作符,结构描述如下:condition_expression ? true_expression : false_expression计算时,如果 condition_expression 为真(逻辑值为 1),则运算结果为 true_expression;如果 condition_expression 为假(逻辑值为 0),则计算结果为 false_expression。assign hsel = (addr[9:8] == 2'b0) ? hsel_p1 : hsel_p2 ;//当信号 addr 高 2bit 为 0 时,hsel 赋值为 hsel_p1; 否则,将 hsel_p2 赋值给 hsel。其实,条件表达式类似于 2 路(或多路)选择器,其描述方式完全可以用 if-else 语句代替。当然条件操作符也能进行嵌套,完成一个多次选择的逻辑。例如assign hsel = (addr[9:8] == 2'b00) ? hsel_p1 : (addr[9:8] == 2'b01) ? hsel_p2 : (addr[9:8] == 2'b10) ? hsel_p3 : (addr[9:8] == 2'b11) ? hsel_p4 ;Verilog 编译指令以反引号 ` 开始的某些标识符是 Verilog 系统编译指令。编译指令为 Verilog 代码的撰写、编译、调试等提供了极大的便利。下面介绍下完整的 8 种编译指令,其中前 4 种使用频率较高。`define`undef在编译阶段,`define 用于文本替换,类似于 C 语言中的 #define。一旦 `define 指令被编译,其在整个编译过程中都会有效。例如,在一个文件中定义: `define DATA_DW 32 则在另一个文件中也可以直接使用 DATA_DW`define S $stop; //用`S来代替系统函数$stop; (包括分号) `define WORD_DEF reg [31:0] //可以用`WORD_DEF来声明32bit寄存器变量`undef 用来取消之前的宏定义,例如`define DATA_DW 32 …… reg [DATA_DW-1:0] data_in ; …… `undef DATA_DW `ifdef, `ifndef, `elsif, `else, `endif`ifdef MCU51 parameter DATA_DW = 8 ; `elsif WINDOW parameter DATA_DW = 64 ; `else parameter DATA_DW = 32 ; `endif当然,也可用 `ifndef 来设置条件编译,表示如果没有相关的宏定义,则执行相关语句。下面例子中,如果定义了 WINDOW,则使用第二种参数说明。如果没有定义 WINDOW,则使用第一种参数说明。`ifndef WINDOW parameter DATA_DW = 32 ; `else parameter DATA_DW = 64 ; `endif`include 使用 `include 可以在编译时将一个 Verilog 文件内嵌到另一个 Verilog 文件中,作用类似于 C 语言中的 #include 结构。该指令通常用于将全局或公用的头文件包含在设计文件里。文件路径既可以使用相对路径,也可以使用绝对路径。`include "../../param.v" `include "header.v"`timescale 在 Verilog 模型中,时延有具体的单位时间表述,并用 `timescale 编译指令将时间单位与实际时间相关联。该指令用于定义时延、仿真的单位和精度,格式为:`timescale time_unit / time_precisiontime_unit 表示时间单位,time_precision 表示时间精度,它们均是由数字以及单位 s(秒),ms(毫秒),us(微妙),ns(纳秒),ps(皮秒)和 fs(飞秒)组成。时间精度可以和时间单位一样,但是时间精度大小不能超过时间单位大小,例如下面例子中,输出端 Z 会延迟 5.21ns 输出 A&B 的结果。`timescale 1ns/100ps //时间单位为1ns,精度为100ps,合法 //`timescale 100ps/1ns //不合法 module AndFunc(Z, A, B); output Z; input A, B ; assign #5.207 Z = A & B endmodule`timescale 10ns/1ns module test; reg A, B ; wire OUTZ ; initial begin A = 1; B = 0; # 1.28 B = 1; # 3.1 A = 0; end AndFunc u_and(OUTZ, A, B) ; endmodule在模块 AndFunc 中,5.207 对应 5.21ns。在模块 test 中,1.28 对应 13ns,3.1 对应 31ns。但是,当仿真 test 时,由于 AndFunc 中的最小精度为 100ps,因此 test 中的时延精度将进行重新调整。13ns 将对应 130100ps,31ns 将对应 310100ps。仿真时,时延精度也会使用 100ps。仿真时间单位大小没有影响。如果有并行子模块,子模块间的 `timescale 并不会相互影响。例如在模块 test 中再例化一个子模块 OrFunc。仿真 test 时,OrFunc 中的 #5.207 延时依然对应 52ns。//子模块: `timescale 10ns/1ns //时间单位为1ns,精度为100ps,合法 module OrFunc(Z, A, B); output Z; input A, B ; assign #5.207 Z = A | B endmodule //顶层模块: `timescale 10ns/1ns module test; reg A, B ; wire OUTZ ; wire OUTX ; initial begin A = 1; B = 0; # 1.28 B = 1; # 3.1 A = 0; end AndFunc u_and(OUTZ, A, B) ; OrFunc u_and(OUTX, A, B) ; endmodule此例中,仿真 test 时,OrFunc 中的 #5.207 延时依然对应 52ns。`timescale 的时间精度设置是会影响仿真时间的。时间精度越小,仿真时占用内存越多,实际使用的仿真时间就越长。所以如果没有必要,应尽量将时间精度设置的大一些。 `default_nettype 该指令用于为隐式的线网变量指定为线网类型,即将没有被声明的连线定义为线网类型。`default_nettype wand该实例定义的缺省的线网为线与类型。因此,如果在此指令后面的任何模块中的连线没有说明,那么该线网被假定为线与类型。`default_nettype none该实例定义后,将不再自动产生 wire 型变量。例如下面第一种写法编译时不会报 Error,第二种写法编译将不会通过。//Z1 无定义就使用,系统默认Z1为wire型变量,有 Warning 无 Error module test_and( input A, input B, output Z); assign Z1 = A & B ; endmodule//Z1无定义就使用,由于编译指令的存在,系统会报Error,从而检查出书写错误 `default_nettype none module test_and( input A, input B, output Z); assign Z1 = A & B ; endmodule`celldefine module ( input clk, input rst, output clk_pll, output flag); …… endmodule `endcelldefine
2022年05月16日
686 阅读
0 评论
1 点赞
1
...
5
6
7