「BUAA-CO」 P1


简介

P1主要是对verilog在预习阶段所学内容的强化,但是显然没有预习阶段的题目那么恶心。P1的题目大致可以分为两类:一类是组合逻辑电路的设计,另一类是时序逻辑电路状态机的设计。下面分别进行说明。

组合逻辑电路设计

组合逻辑电路的设计相对简单,主要考察对verilog语法的掌握以及对基本逻辑电路的理解。说白了就是程序设计换一种语言写而已,不会用很难的算法为难大家的。

时序逻辑电路状态机设计

状态机的设计相对复杂一些,主要考察对状态机原理的理解以及verilog实现状态机的能力。状态机的设计一般分为以下5个模块:

  1. 变量定义模块
  2. initial模块
  3. 时序逻辑状态转移模块
  4. 组合逻辑次态计算模块
  5. 组合逻辑输出计算模块
// 1. 变量定义模块
reg [n-1:0] state; // 当前状态
reg [n-1:0] next_state; // 下一个状态

// 2. initial模块
initial begin
state = INITIAL_STATE; // 初始化状态
next_state = INITIAL_STATE; // 初始化下一个状态
end

// 3. 时序逻辑状态转移模块
always @(posedge clk or posedge reset) begin
if (reset) begin
state <= INITIAL_STATE; // 复位状态
end else begin
state <= next_state; // 状态转移
end
end

// 4. 组合逻辑次态计算模块
always @(*) begin
case (state)
STATE_0: begin
if (input_condition) begin
next_state = STATE_1;
end else begin
next_state = STATE_0;
end
end
STATE_1: begin
// 其他状态转移逻辑
end
// 其他状态...
default: begin
next_state = INITIAL_STATE; // 默认状态
end
endcase
end

// 5. 组合逻辑输出计算模块
always @(state) begin
out = (state == TARGET_STATE) ? 1'b1 : 1'b0; // 输出逻辑
end

掌握了这个基本框架之后你的状态机就不会经常因为时序问题出bug了。同样的,状态机的设计也可以分为两种方法:一种是使用真值表表示状态机,另一种是使用常规逻辑表达式表示状态机。按照另一种分类方式,可以分为Moore型和Mealy型状态机设计。思路跟P0大同小异,再套用上述提到的模板即可。笔者帮大家整理好了对比代码,上传到了github仓库,大家可以参考理解,重点关注一下组合逻辑输出计算模块的区别。下面我们重点讲一下状态机Plus版–一般用在string stream中,对应上机考试的最后一题。

状态机的Plus版

Plus版一般是指在一个模块中设计两个相互独立但又有联系的状态机。举个例子:

给定按时钟输入的 ASCII 字符流,其中包含若干个由 "{" 与 "}" 包围的简化 JSON 对象(对象之间由空格分隔)。每个键值对的键和值均用双引号包围 "key":"value"。若对象中出现空字符串键或空字符串值(即 ""),则该对象非法,字段数记为 0。计算每个对象的字段数输出到 cur_num,并维护历史最大合法字段数输出到 max_num。

这是一道上机考试回忆版题目,可能有的细节不甚详尽,还请大家多多包涵。

本题的解题思路是在一个模块中设计两个状态机:一个状态机用于维护”IDLE”、”READ”、”CHECK”三个状态,识别JSON对象的开始和结束,第二个状态机负责统计字段数并更新最大值。这里重点和难点是第二个状态机的设置。

我们用变量number1来统计"的数量,用tmp_cnt来统计两个引号之间的字段数,用cur_num来记录当前对象的字段数,用max_num来记录历史最大字段数。当number1为偶数时,如果tmp_cnt为0,说明出现了空字符串键或空字符串值,此时cur_num置0;否则cur_num加1。每当遇到}时,比较cur_num和max_num的大小,更新max_num。

详细代码实现参见个人GitHub仓库:https://github.com/Cordial-Kid/BUAA-CO/blob/main/P1/json.v

可能踩的坑

在只有在组合逻辑电路中才能实现sum = sum + i这类型的语句,在时序逻辑电路中是不允许的。

always @(*) begin
sum = 0; //这一步很重要
for(i = 0; i < 8; i = i + 1) begin
sum = sum + i;
end
end

Lyrics Sharing

若不是你突然闯进 我生活
我怎会把死守的寂寞 放任了
爱我的话你都说
爱我的事你不做
我却把甜言蜜语
当作你爱我的躯壳
你的悲伤难过我不参破
我也会把曾今的且过 当施舍
不去计较你太多
从此你在我心里
只剩绿色

文章作者: Cordial-Kid
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Cordial-Kid !
  目录