题目
听肥子说这题是去年他舍友出的,比老师出的还难,果然……刚开始看还没觉得怎么样,做了一会觉得不行了,做不下去了:(
看题
光题干就这么长,大佬,果然是大佬。
分析
假装写个分析吧,其实还没明白呢……
好吧,假装写也写不出来啊……
放弃分析。
算了还是写写。
真的分析
这个题目很难,我觉得主要是在于时序的关系没有把握好。又是双工的,接收端只有同步时钟,好麻烦啊,好难想啊,画图也不是很好画啊……
看了要求也是云里雾里,写了一半才恍然大悟:是这样的,接收端一共有四个寄存器0~3,发送端依次往里面发送数据,发送的数据每次右移两位;发送完之后,再从接收端寄存器reg3中读取数据,也就是右移六位的数据。
要注意的是,这里的数据,是指除了地址和I/O判别信号之外的8位数据位。每次传输的数据,不只是data_in的8位,就像题目里第四部分描述的那样,每一帧数据共有十六位,第一位是I/O控制信号,接着的七位是地址位,用来指出所选中寄存器的地址,最后的八位才是数据位。
还有一个难点,是题目要求所有的数据都在sclk的上升沿产生,接收数据再下降沿采样,这就让我很疑惑,在采样时如果用组合逻辑,就不符合下降沿这个特性,而使用时序逻辑时,又会导致接收到的数据和发送的数据相差一个半周期,会使时序更加混乱,难以控制。(这个问题老师肯定会给我解答的!!!等着他上课吧)
结果
虽然糊里糊涂,但是编了十个小时大概,还是除了结果,虽然结果的出现有些拼凑在里面……
上图!!
啊好了,我把拼凑的那点改正过来了,现在是光明正大的出结果了!!
再放一张图纪念一下好了,现在的问题就剩下我所困惑的时序问题了,怎么才能不后推那么多呢?……好难受啊
好了,现在是零点两分,我终于知道自己的困惑在哪了,我是个菜鸡实锤了。
我一直以为时序逻辑里,(不知道怎么回事),我就觉得这个上升沿<=赋的值要到下一个上升沿才能赋到上面……好吧,我……打扰了。
终于终于,改好了!!!
其实,如果不是我一直犯浑,好像这个题也不是很难的样子啊……说实话时序那里和我还没完全明白,我再捂一捂先。
第二天
我我我……我好像知道了!!!
是这样,判断条件里的是边沿之前的,而下面赋值的语句,等号后面的值就是边沿之后的值了!!!
再简单点说,就是:条件满足了的时候,再下一个边沿赋值;如果条件一直是满足的,那就第一个边沿就赋值就好了!
用肥子的话说,就是D触发器嘛,满足了条件,就会在下一个时钟周期边沿赋值,而如果条件一直是满足的,就直接在边沿赋值了。赋值的条件,才是受时序约束的东西,必须要在边沿之前就满足才行!
这样一来,我又对比了之前困惑的一些模块,一些看似矛盾的时序,就都清晰了唉!
太感人了,那就没剩下什么问题了!完活!
这次作业里踩到的雷
说说我所犯的愚蠢的错误吧……太丢人了……
- testbench里实例化的时候,每个模块的输入输出参数要跟模块里的顺序对齐!!!
这个错误还是肥子同学帮忙找出来的……害,每次写作业都要麻烦他,幸亏关系好。 - 上面所说的关于时序的困惑,一定要记得!!!不然会无端生出很多的顾虑啊!
- 还有……每个模块开始的定义参数……看来我是记不得了,竞赛前看看吧……反正开卷,抄一个格式好了。
- 还还有,如果一个数据是输入的,比如说这次作业里的data_in,就不能直接在data_in 中移位,应该另外设置一个data,在data里面移位。(血的教训,改了好久才找出来是这个原因……编译错误提示就只说 ileagal reference 什么的QAQ)。
果然,阻挡人类进步的都是一些愚蠢的错误啊。
好几天之后
经过这几天群里的讨论也好,老师的指导也好,大佬的代码鞭策也好,又在基础上做了很多改进,比如说master端的,我增加了一个回合计数器,用来记录现在到了回合的哪一部分,这样就非常方便的设计读写步骤和分配地址;还在接收端做了改善(我现在也不清楚改没改了,我觉得我对接收端的功能更加了解了而已,其实程序跟刚开始的时候相差无几)。
害,下次组队的时候要记得这个教训,绝对不找学弟学妹了。