语句块模拟检查 P1_L1_BlockChecker#
一.题目要求#
1.题目描述#
输入ASCII字母和空格,一个或多个连续出现的字母构成单词,单词不区分大小写,单词之间由一个或多个空格分隔开。检查工具检查自复位之后的输入中,begin和end是否能匹配。
注:
- 匹配的begin必须出现在end之前
- 一个begin只能匹配一个end
- 允许出现嵌套
- 出现不能按照规则匹配的begin或end,则匹配失败
- 保证在模块使用前进行复位
2.IO定义#
| 信号名 | 方向 | 描述 |
|---|
| clk | I | 时钟信号 |
| reset | I | 异步复位信号 |
| in[7:0] | I | 当前输入的ASCII码 |
| result | O | 当前输入能否完成begin和end匹配 |
注意:输出result为“当前”的判断结果,即随着状态更新
2.状态转移图#

解释:
- 所有的单词都以空格表示结束对应回到S0状态
- 如果之前没有出现过begin就出现end,之后无论输入什么都会输出0,设置为单独的状态S10,这个状态是自环的,无论输入什么都会回到S10,并输出0.
3.verilog代码实现#
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
| module BlockChecker (
input wire clk,
input wire reset,
input wire [7:0] in,
output reg result
);
reg [31:0] begin_cnt;
reg [15:0] status;
`define S0 16'b0000_0000_0000_0001
`define S1 16'b0000_0000_0000_0010
`define S2 16'b0000_0000_0000_0100
`define S3 16'b0000_0000_0000_1000
`define S4 16'b0000_0000_0001_0000
`define S5 16'b0000_0000_0010_0000
`define S6 16'b0000_0000_0100_0000
`define S7 16'b0000_0000_1000_0000
`define S8 16'b0000_0001_0000_0000
`define S9 16'b0000_0010_0000_0000
`define S10 16'b0000_0100_0000_0000
always @(posedge clk or posedge reset) begin
if(reset)
begin
begin_cnt <= 32'b0;
status <= `S0;
result <= 1'b1;
end
else
begin
case (status)
`S0: //empty
begin
if(in == " ")
begin
status <= `S0;
end
else if (in == "e"||in == "E")
begin
status = `S7;
end
else if (in == "b"||in == "B")
begin
status = `S1;
end
else
begin
status = `S6;
end
end
`S1: //b
begin
if(in == "e"||in == "E")
begin
status = `S2;
end
else if (in == " ")
begin
status <= `S0;
end
else
begin
status <= `S6;
end
end
`S2: //be
begin
if(in == "g"||in == "G")
begin
status <= `S3;
end
else if (in == " ")
begin
status <= `S0;
end
else
begin
status <= `S6;
end
end
`S3: //beg
begin
if(in == "i"||in == "I")
begin
status <= `S4;
end
else if (in == " ")
begin
status <= `S0;
end
else
begin
status <= `S6;
end
end
`S4: //begi
begin
if(in == "n"||in == "N")
begin
status <= `S5;
result <= 1'b0;
end
else if (in == " ")
begin
status <= `S0;
end
else
begin
status <= `S6;
end
end
`S5:
begin
if(in == " ")
begin
status <= `S0;
begin_cnt <= begin_cnt + 1;
end
else
begin
status <= `S6;
if(begin_cnt == 32'b0000)
begin
result <= 1'b1;
end
else
begin
result <= result;
end
end
end
`S6:
begin
if(in == " ")
begin
status <= `S0;
end
else
begin
status <= `S6;
end
end
`S7:
begin
if(in == "n"||in =="N")
begin
status = `S8;
end
else if (in == " ")
begin
status <= `S0;
end
else
begin
status <= `S6;
end
end
`S8:
begin
if(in == "d"||in == "D")
begin
if(begin_cnt == 32'b0001) //只剩余一个begin 可以完成配对
begin
status <= `S9;
result <= 1'b1;
end
else
begin
status <= `S9;
result <= 1'b0;
end
end
else if (in == " ")
begin
status <= `S0;
end
else
begin
status <= `S6;
end
end
`S9:
begin
if(in == " ") //确定匹配到的一定是end
begin
if(begin_cnt == 32'b0) //还没有出现过begin 这种情况无论后便出现什么都是0
begin
status <= `S10;
result <= 1'b0;
end
else if(begin_cnt == 32'b1)
begin
status <= `S0;
result <= 1'b1;
begin_cnt = 32'b0000;
end
else if(begin_cnt > 32'b1)
begin
status <= `S0;
result <= 1'b0;
begin_cnt = begin_cnt - 32'b0001;
end
end
else //匹配到的不是end
begin
status <= `S6;
if(begin_cnt==32'b0)
begin
result <= 1'b1;
end
else
begin
result <= 1'b0;
end
end
end
`S10:
begin
status <= `S10;
result <= 1'b0;
end
default:
begin
status <= status;
result <= result;
end
endcase
end
end
endmodule
|
4.一个坑点#
`S5:
begin
if(in == " ")
begin
status <= `S0;
begin_cnt <= begin_cnt + 1;
end
else
begin
status <= `S6;
if(begin_cnt == 32'b0000)
begin
result <= 1'b1;
end
else
begin
result <= result;
end
end
end
在进行单词begin的匹配时,需要对是否成功的匹配到begin做判断,一开始在两种之间来回改,后来才想到这是两种情况应该使用分支结构:
如果之前没有成功匹配过begin:现在也没有匹配到begin,则下一周期输出应该是1,在这种情况下应当将匹配N时改动的result复位回1
如果之前成功匹配过begin:当前的匹配结果不应当影响之前的结果
而不应当进行复位,如例子
这时即使第二次匹配begin失败,输出result也应当为1
5.特别致谢hugo && xmgg 帮忙看我的bug QAQ#