P1总结
P1L0表达式状态机
!!!理解非阻塞赋值
<=同时赋值
P1_L1_Block_checker
clr 异步清零
放在三段式的第一个li1
2
3
4
5
6
7
8always @(posedge clk or posedge clr) begin
if(clr == 1)begin
state <= 0;
end
else begin
state <= next_state;
end
end
注意发现异常情况后状态不能清0
因为在本代码的设计中状态0是开始查找的起始状态
Isim仿真时改变信号值的表现形式,radix
没发现的样例:
因为我的逻辑是发现有一个begin就增加match,发现一个end就减少match,
发现有其它后缀就撤销增减操作,我通过设置erro状态0来表示end先出现的情况,
且此时不再有其它变化。但这种方式也会有一定的问题:end endc
出现一个end,match由1变为0;
出现endc,撤销,match由0变为1,输出result=1
endc end
出现endc,撤销操作,match由1变为2
出现一个end,match由2变为1,输出result=1
解决方法:
增加 last_match,
当且仅当last_match=match=0时才确认为err状态,且不参与撤销操作
这里放一下完整的代码,同时也是用了三段式状态机的写作手法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154module BlockChecker(
input clk,
input reset,
input [7:0] in,
output reg result
);
reg [3:0] bg_num;
reg [3:0] next_bg;
reg [2:0] end_num;
reg [2:0] next_end;
reg [31:0] last_match;
reg [31:0] match;
reg [31:0] next_match;
reg [7:0] last_in;
initial begin
bg_num <= 4'b000;
end_num <= 3'b000;
match <= 31'b1;
last_in <= " ";
last_match <= 31'b1;
end
always @(posedge clk or posedge reset)begin
if(reset)begin
bg_num <= 4'b000;
end_num <= 3'b000;
match <= 31'b1;
last_in <= " ";
last_match <= 31'b1;
end
else begin
match <= next_match;
bg_num <= next_bg;
end_num <= next_end;
last_in <= in;
last_match <= match;
end
end
always @(*)begin
if(bg_num == 4 && (in == "n" || in == "N") && match > 0)begin
next_match = match + 1;
end
else if(bg_num == 5 && !(in == " ") && match > 1)begin
next_match = match - 1;//撤销
end
else if(end_num == 2 && (in == "d" || in == "D") && match > 0)begin
next_match = match - 1;
end
else if(end_num == 3 && !(in == " ") && last_match > 0)begin
next_match = match + 1;//撤消
end
else begin
next_match = match;
end
case (bg_num)
0:
begin
if(last_in == " " && (in == "b" || in == "B"))begin
next_bg = 1;
end
else begin
next_bg = 0;
end
end
1:
begin
if(in == "e" || in == "E")begin
next_bg = 2;
end
else begin
next_bg = 0;
end
end
2:
begin
if(in == "g" || in == "G")begin
next_bg = 3;
end
else begin
next_bg = 0;
end
end
3:
begin
if(in == "i" || in == "I")begin
next_bg = 4;
end
else begin
next_bg = 0;
end
end
4:
begin
if(in == "n" || in == "N")begin
next_bg = 5;
end
else begin
next_bg = 0;
end
end
default:
begin
next_bg = 0;
end
endcase
case (end_num)
0:
begin
if(last_in == " " && (in == "E" || in == "e"))begin
next_end = 1;
end
else begin
next_end = 0;
end
end
1:
begin
if(in == "N" || in == "n")begin
next_end = 2;
end
else begin
next_end = 0;
end
end
2:
begin
if(in == "D" || in == "d")begin
next_end = 3;
end
else begin
next_end = 0;
end
end
default:
begin
next_end = 0;
end
endcase
end
always @(match)begin
result = (match == 1) ? 1 : 0;
end
endmodule
课上
很顺利地过了第一个题
第二个题有关赋值的部分卡了一会,没看见取query[2:0]卡了半天
第三个题完全做复杂了,不敢想象(?)
吃了没看题的亏,果然一上机就会变蠢md
note_recorder
看题!!!:如果是输出个数的话,取query[2:0]
注意非阻塞赋值的用法(hh原来之前只是浅浅了解)
注意:
非阻塞赋值:
先对所有值进行一个快照
用快照的值进行计算,再统一赋值给左边
尤其注意左右两边同时用到一个表达式值的情况:1
2cnt[note[0]] <= cnt[note[0]] - 1;
note[0] <= note[1];
右边的cnt[note[0]]是note[0]
左边的note[0]实际上是note[1]
解决办法:1
2cnt[note[0]] = cnt[note[0]] - 1;
note[0] <= note[1];
另外:
动态事件队列的优先级:
- 阻塞赋值
- 计算非阻塞赋值语句右边的表达式
- 连续赋值
- 执行display命令
json
状态转移:
(考虑到两次输入之间没有空格)
输入{前有两种可能状态:state=0或者state=结束状态
注意3种结束方式:
- 正常结束
- 空
{}结束 - 有无效字符串结束(锁定到erro状态,直至此次输入结束)

