P1

Wesley13
• 阅读 597

通过本文,您的收获可能有:从课下部分,了解一些基本部件搭建时可能遇到的坑点,稍微深入一点理解两种状态机的区别;从课上测试部分,可以了解重点的考察内容,明白设计时状态机的类型在测试中的重要性。

课下测试部分:

课下测试主要考察了splitter的实现,ALU的实现,格雷码计数器的实现,扩位器的实现,以及合法表达式判别的有限状态机问题。本次课下部分比较简单,正好让下周工作量爆炸的我缓一口气。

1.splitter实现:

实现的方式就是用拼接运算符(大括号)直接把信号拼起来。需要注意的一点是,如果发现提交之后是CE,那么一定要检查一下是不是交错了文件,以及,文件名是不是正确。神TMD知道我之前就写过一个叫spliter的东西,然后交上去了,后来反应过来好像日期对不上;接着我又交现在的,还是CE,过了好久我才反应过来:我文件名字拼写从很久之前起就是错的。真是要命的低级失误!考虑到课上测试的时候会有3分钟保护时间不让提交,所以这样的失误会耽误时间,也会很影响心情,一定要避免。

2.ALU的实现:

关于如何将无符号数变成有符号数,请移步:https://blog.csdn.net/adaliu1998/article/details/80459262

在verilog中运算时,如果同时出现有符号数和无符号数,有符号数会被处理为无符号数进行运算;所以当{hi,lo}不加signed时,$signed(A)的有符号化无效,仍然是作为无符号A

3.扩位器的实现:

加强版的第一题,仍然利用拼接运算符即可。不会写if_else或者case的话还是最好回归课本,把前七章重新学一遍,会省很多事情。室友昨天因为case没有放在过程块always中,debug好久,这在课上可是耽误不得!熟悉基本语法很重要!可以通过hdlbits.01xz.net上的练习来熟悉语法。

4.格雷码计数器:

也是属于语法回顾题,考察了case语句。坑点可能是reset忘记给overflow置零,或者是在溢出之后回到0的时候由于不合理的逻辑,导致overflow被误置为0。同步复位信号的always块的最开始只需要写always @(posedge clk)即可,如果加上了其他东西,比如写成了always @(posedge clk,clr)之类的,就不是同步复位了,有兴趣的可以单步调试一下,会发现出了意想不到的错误。另外,记得初始化(其实自己测试的时候应该就能想起来应该先初始化,不然会出现不定值)。

5.表达式状态机:

P1

这个状态机我考虑了四个状态:没有字符的empty状态,是合法表达式的yes状态,必定不是表达式的hopeless状态(比如上来就是个符号,或者途中出现连续数字,或者出现连续符号,更有甚者,出现题目要求之外的符号),还有希望是表达式的hope状态(比如从1变成1+的这种可以通过加数字变成合法表达式的情况)。状态想好之后,转移也比较容易能写出来了。不清楚评测数据有没有输入非法字符,为了稳重,还是要考虑0-9以及+*之外的字符。

异步置位的写法:要clr为1,就要把状态置为0,另外,本题的数据是在时钟上升沿才会传过去的,综上可知,always应该写成**always @(posedge clk,posedge clr)**,如果加了in的变化(always @(posedge clk,posedge clr,in)),也会出现上一个题中说到的意想不到的错误,可以自行尝试。//2019.10.21补充,为什么要在触发条件里面写posedge clr呢?因为我们要求异步复位,也就是说clr只要变为1,则从变成1的那一刻起就应该马上重置。如果把posedge clr写成了clr,在ISE语法检查的时候不会报错,在HDLBits上会CE,如果又干脆不写clr的变化,就成了同步复位,如图:P1

至于always @(posedge clk,posedge clr)与always @(posedge clk,clr)在ISE中波形的区别,****这属于很细节的问题了,有意者可以自行设计testbench进行探索。

本题我犯了一个很沙雕的错误:状态的编码采用独热编码是4位,但是我定义的state变量最开始是reg state;事实上应该是reg [3:0] state。这个地方如果错了,测试的时候会发现很多该变化状态的时候没有变化。以后一定要引以为戒啊!!!

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

备考P1阶段经验总结:

做了hdlbits.01xz.net上的问题:Lemmings2 ,以练习有限状态机的verilog实现,发现做该题的时候出现的问题蛮多,且十分典型,值得反省:

1.一个玄学问题:if-else报错但case没问题。这个问题出现在case中嵌套使用if-else时,至今也不知道为什么错了,只知道只要改成case就完全没问题。不管了

2.信号位数问题:这个问题在之前P1课下测试里面已经犯过了,这次犯得更难以发现一点:赋值时rightmove=3'b001写成了rightmove=001,然后就会出现以下报错:

P1

 重要的是后两行报错信息。在ISE中并不会给出这种报错,而这个网站为了帮助学习给出了这个报错,才让我意识到可能是赋值时漏写了位数和进制。推荐把一些常用的数都声明成parameter型,然后仔细检查两遍parameter,仔细考虑一下各个parameter的命名怎样好,这样在以后赋值的时候就不会出现这种难以察觉的问题了。

3.reset。没错又是复位,这次不是不会同步异步,而是干脆没写。。。这个在自己做测试的时候还是容易发现的。

4.初始化是个好东西,希望你写的时候记得它。

5.verilog下的moore型与mealy型状态机:

具体如何去写,参见ISE模板(这几天见到的版本太多已经有些凌乱了)

用verilog的时候我没有明确区分过,因为我把所有的逻辑都集中在case里面了,这样很不好!还记得P0的时候有很多同学因为状态机的类型错误,吃了大亏,所以要慌,问题很大!之后两天的训练里面要试着把状态转移,状态保存和输出逻辑分开写。

考虑下面的状态机:(图片来自P1教程部分)

P1

 猛的一看,这好像是个mealy型状态机,因为它写的代码看起来是输入和状态共同决定输出。但是,仔细想一下,如果现在是3状态,即state=3被存到了状态存储电路中,状态转移电路里面需要转换的是state=3与一个输入in,时钟上升沿时,in与状态转移电路里的state (=3)算出来一个新状态,然后,新状态瞬间传到了状态存储电路里面,在这一瞬间之后,状态存储电路就被锁死了不可变了,而我们的输出,就是由这时候被锁住的状态决定的。综上所述,这是一个moore型状态机(ISE模板中便是以这个给出的)

更新:关于mealy型状态机

Mealy型状态机的输出不仅仅在时钟上升沿时改变,而Moore型状态机的输出只在时钟上升沿时改变。所以模板中输出使用的assign

课上测试:

第一题:考察有符号数的比较,四位有符号数输入,输出较大的一个。有符号数输入的是补码。这个需要了解补码是怎么回事儿,正数的补码是本身,负数的补码是这个数除了符号位之外的位取反加1。考试的时候为了保险起见,我先写了一个简单的输入输出,写了一个tb,仿真了一下,把输出调成有符号数,嗯,的确是这个规则(突然变得有底气了)。然后就是比较了。这个先比符号位,比不出来再从高到低逐位比(不知道为什么题目不让用>,<,<=号)。写个tb试试各种情况即可。

经验:有不太确定的知识点可以利用工具进行一波验证,比如上次的算数右移(用Logisim自带移位器造输入输出看输出规律)和这次的原码补码。

第二题:又是卖东西的状态机,和p0的差不多,只是题目要求有点绕。注意退币的两种情况:输入2'b11或者大于等于2元。注意reset是异步复位,前面已经介绍过异步复位办法,所以总体不难写。读题多花点时间是应该而且有必要的,这个题的退币以及状态转移是需要仔细读题的,有时还需要仔细读题目给出的测试波形(本题的测试波形能读得和自己的理解一样的话,题意理解上就没什么问题了)。写代码时注意上面说的易错点,并做足下面的测试,有很大希望不用被卡等待时间。

经验:题意看不懂时,逐步分析题给波形。

第三题:正则表达式匹配(此处是幂函数的格式),和p1的差不多,就是状态有所增加(我写了9种,可能多了)。记忆版题面是匹配满足 ^[+-]?(\d+\*)?x(\^[+-]?\d+)? 的表达式。根据题意,从none开始,考虑下面几种输入:+,-,数字,^,x,*,即可逐步找到每个可能出现的状态。常数较多,写parameter比较好。

经验:建立状态机要慢,coding手速要快。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Easter79 Easter79
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Android蓝牙连接汽车OBD设备
//设备连接public class BluetoothConnect implements Runnable {    private static final UUID CONNECT_UUID  UUID.fromString("0000110100001000800000805F9B34FB");
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这