BUAA-CO-P1-课下

BUAA-CO-P1-课下

FSM

T1_饮料机

饮料价格为2元,顾客只能选择投0.5元、1元、退回所有硬币、不投。当投币总额不足2元,drink置0,当投币总额超过2元,drink置1,同时back置超出的钱币。若选择退回所有硬币,back置退回钱币。

出货的周期仍然可以投币

信号名 方向 描述
clk I 时钟信号
reset I 异步复位信号,回归初始状态,所有输出为0
coin[1:0] I 投入的硬币,2’b00代表未投币,2’b01代表投入5角,2’b10代表投入1元,2’b11代表按下退币按钮
drink O 顾客是否能获得饮料,1代表是,0代表否
back[1:0] O 售货机返还的钱数,2’b00代表不返还,2’b01代表5角,2’b10代表1元,2’b11代表1.5元

根据“出货的周期仍可以投币”得知,这一定是一个Mealy机。如果是Moore机,显然需要到达一个“输出状态”,同时出货,再继续处理投币,即出货周期不接受投币。而Mealy机可以在转移的同时处理投币。

Mealy机可以把输出和状态转移写在一起,不过这样的话需要把输出设置成reg,并且不要忘记在always块头部进行初始化。

T2_表达式状态机

表达式定义:单个数字是表达式;如果X是,Y是,那么X+Y和X*Y也是

每个时钟上升沿读入一个ASCII码字符,判断目前已读入的所有字符组成的字符串是否符合表达式定义

有点小坑的一道题。根据定义,12+341++等包含连续数字或符号的字符串都不是表达式。但是发现,status只能记录前一个状态,并不能表示出“之前有没有错误”(显然,一个非表达式无论与什么内容拼接,都不能再得到表达式)。

举个例子,输入1,状态表示“读入数字”,再输入2,状态依旧表示“读入数字”,这时如果读入+3,状态将显示“数字、字符、数字”,即“是表达式”,但这其实并不是表达式。

为解决这个问题,只需要加入另一个寄存器error,记录曾经出现过的错误(例如数字后又输入了一个数字),当error == 1时无论如何输出“错误”,并且仅在reset时才清零。

T3_带括号的表达式状态机

只考虑带一层括号的情况,如(1+2*3),不需要识别嵌套括号

我写状态机的原则是除status以外,其他变量越少越好,这样可以简化输出时的判断条件,避免一堆if...else...&&...||...混杂在一起,导致难以发现的bug。我的舍友为了减少状态数量,多加了一个left变量,以记录是否有未匹配的左括号,导致了一些两个人都de不出来的bug,非常难受…

我的状态图:

start F ( (a (a+ (a+b F+ num out=1 ( num ) out=1 char num char ) out=1 char (

testbench的优雅写法

input_string
1
2
3
4
5
6
7
8
9
10
reg [0:1023] S = "input_string";
integer i = 0;
initial begin
while(!S[0:7]) S = S << 8;

for(i = 0; S[0:7]; S = S << 8) begin
in = S[0:7];
#5;
end
end

rofie简直是个天才,完美解决了与字符串相关的testbench太难写的问题。定义了reg[0:1023]来存储要输入的字符串(个人理解,从小端开始是为了防止取值时不知道引脚的具体数值),由于字符串被放在最右侧,所以要不断左移,直到开始有内容,随后每次读取0:7位的内容输入到in7:0

作者

OWPETER

发布于

2024-10-05

更新于

2024-12-02

许可协议

评论