当前位置: 首页 > news >正文

Verilog和FPGA的自学笔记5——三八译码器(case语句与锁存器)

今天说说用Verilog描画三八译码器……

跟锁存器啥关系??

记得第一次看见三八译码器时,看见的是个这:

在这里插入图片描述
没错,数字电路技术基础来也!
到FPGA里时,一想,不对啊,这么多逻辑,全写完还活不活了……
当时本人也懒得动脑子,决定直接看答案(Ctrl+C Ctrl+V中……)

always@(*) begincase(sel)3'b000 : out = 8'b0000_0001;3'b001 : out = 8'b0000_0010;3'b010 : out = 8'b0000_0100;3'b011 : out = 8'b0000_1000;3'b100 : out = 8'b0001_0000;3'b101 : out = 8'b0010_0000;3'b110 : out = 8'b0100_0000;3'b111 : out = 8'b1000_0000;default : ;endcase
end

还没等Ctrl+C就明白了,就一堆switch-case啊 (当时以为是switch) ,哦原来这么写的啊……晕死。

于是这件事启发了我:原来那经典的根据云里雾里的真值表设计逻辑电路的破题,在FPGA里压根就不算事,直接把它抄进来不就完了嘛!

对,其实我们学设计译码器不是来学逻辑表达式的,而是来学case语法的……捂脸。

case语句

case作为过程性语句,也不能自个待着,它必须放进用always搭建的过程块中去。

always@(*) begincase(敏感信号)情况1 : 逻辑1;情况2 : 逻辑2;……情况n : 逻辑n;default : ;endcase
end

小贴士:

  1. Verilog不是C++,硬件做并行处理无需写break;
  2. Verilog不是C++,Verilog中要列清楚所有可能的结果(至于为啥待会再说)
  3. Verilog不是C++,别写switch-case,记得结尾要写endcase。(越来越感觉像asm)
  4. 暂时没了,以后想起来再补充,先占个位……

为什么要讲锁存器??

填开头的坑啊……其实锁存器和译码器不能说关系不大吧,至少也可以说是一点关系没有。

学过数字电路的我们都知道,锁存器和触发器的区别就在于电平触发还是边沿触发。
在不少FPGA中,因为这样或那样的原因,抖动是不可避免的,所以绝大部分情况下,弄一个锁存器出来是要命的。

我们要避免锁存器的产生。

那跟译码器啥关系啊?因为不看小贴士的人可能会无意中造个latch出来。(看不懂的说明英语该补补了……)

敲黑板:

包含在不带时钟的always语句的if或者case语句的不完整描述将被综合产生latch。

什么玩意?不会长句变短句啊?cos全国语文新课标卷语言文字运用……

换句话说,如果你在always @(*)的语句块里面写了个if或者case,但遗漏了部分情况,就会综合出个锁存器……

至于为啥昂咱也不知道,咱也不敢问。

不过我一直用vivado,vivado这个样子,至于别的EDA工具会不会这样咱也没用过不清楚。(不是贬低vivado,这里我也不清楚为啥,但承认vivado是目前最好的EDA开发软件,优化算法真的很厉害)

对应的代码放张图给你看:(下部是vivado中的细化设计)
在这里插入图片描述
再看个情况写全了的:
在这里插入图片描述
显而易见吧?

当然下面这种写法也不会产生latch:

always @(*) begincase(key)1'b0:led = 0;1'b1:led = 1;endcase
end

有的教程认为不写default就会产生latch,这种说法是错误滴!

多位宽的reg

看译码器的示例代码时,有人可能对这个有疑惑:out = 8’b0001_0000;

一个out咋可能对应8个信号捏?
哈哈这当然不可能,毕竟三八译码器还是8路输出呢。
out的数据类型是这样写的:

output  reg [7:0]   out   //在module定义的

类似C++数组,reg后面的[7:0]表示从0位开始,7位结束的8位寄存器。

output  reg [7:0]   out1,out2

以这样的方式可以定义多个相同类型的多位宽寄存器。

如果有人就是不想从0开始,觉得别扭,非要从某个自己喜欢的数开始,也行。
比如这样:

output  reg [7:2]   out

这就解释了什么是鹤立鸡群……(因为一般人都会从0开始)

同理,sel(三位地址输入信号)也是用[2:0]实现的,只是换成了线网类型wire:

wire [2:0] sel;

需注意sel并不作为module的端口,只是一个存放数值的中间量而已。

位拼接运算符

所以分别定义三个输入:

intput A,
intput B,
input C

接着用位拼接运算符“{}”进行拼接:

assign sel = {A, B, C};   //用法非常清晰就不多说了吧……

位拼接也是一种逻辑运算,需要放进assign或者always里。
Verilog这一点确实不错,不用自己手写移位了。

所有细节都介绍完啦!试着自己写写吧!

module decoder3_8(input A,input B,input C,output  reg [7:0]   out
);wire [2:0] sel;assign sel = {A, B, C};     //使用assign语句位拼接always@(*) begincase(sel)3'b000 : out = 8'b0000_0001;3'b001 : out = 8'b0000_0010;3'b010 : out = 8'b0000_0100;3'b011 : out = 8'b0000_1000;3'b100 : out = 8'b0001_0000;3'b101 : out = 8'b0010_0000;3'b110 : out = 8'b0100_0000;3'b111 : out = 8'b1000_0000;endcase
endendmodule

好啦,内容到这里就结束啦!欢迎大家在评论和我多多交流~~

如果有不明白或错误之处,也希望大家在评论区给出,帮助大家的同时也能再次提升自己对于FPGA和Verilog的理解,感谢大家!!

系列链接:
上一篇:Verilog和FPGA的自学笔记4——多路选择器(always语句)
下一篇:码字ing……

http://www.dtcms.com/a/469601.html

相关文章:

  • Mpi多机通信环境搭建(2台机器)
  • 简述网站制作流程图如何免费注册淘宝店铺
  • 人工智能在数学教育中的应用 | 现状、探索与实践
  • VSCode括号高亮插件(vscode插件)bracket pair、活动括号对、括号线(未完全检查)
  • FPGA强化-串口rs232
  • 为何建设银行网站无法登陆公司官网开发
  • 2020年多媒体应用设计师考试上午真题
  • 构建算法远程开发调试环境
  • 南通网站建设系统方案龙岩网站设计 信任推商吧做词
  • Vivado进阶-Fpga中的mem的综合和应用
  • Jmeter设置负载阶梯式压测场景(详解教程)
  • 网站运营专员做六休一wordpress托管网站
  • WPF用户控件和依赖属性
  • 位运算 和 逻辑运算 以及 位运算指令
  • 工地招聘网站广告设计与制作视频
  • C++右值语义解析
  • java-高级技术(单元测试、反射)
  • 厦门做网站公司有哪些邯郸
  • Spring Boot 项目集成 Gradle:构建、测试、打包全流程教程
  • 电商主要是做什么工作东莞seo收费
  • SAP MM 通用物料移动过账冲销接口分享
  • 设计logo免费网站电商网站对比表格
  • SAP Vendor Invoice Management by OpenText (VIM)
  • 用 PyQt5 + PyPDF2 做一个“智能分页”的大 PDF 拆分器(含 GUI 与命令行双版本,附完整源码)
  • 芯片结构简介-arm/x86
  • Agentic AI 教程与 AI 编程入门:从基础到实战(含代码、流程图与 Prompt)
  • 做一个公司网站一般多少钱自己做的网站怎么放视频
  • 开源软件License科普:GPL/LGPL/Apache/木兰等license解析
  • React闭包陷阱(stale closure)介绍(React状态更新引用旧值)解决方法:使用函数式更新写法
  • 【Java数据结构】Map 与 Set 接口全解析