2023 BUAA CO review: P1
课下提交
Q1 P1_L0_splitter
使用 搭建一个32位 , 给定一个32位的二进制数作为输入,将其划分为四个8位的二进制数作为输出。
模块名:splitter
信号名 | 方向 | 描述 |
---|---|---|
A[31:0] | I | 输入的二进制数 |
O1[7:0] | O | A的[31:24]位 |
O2[7:0] | O | A的[23:16]位 |
O3[7:0] | O | A的[15:8]位 |
O4[7:0] | O | A的[7:0]位 |
没什么好说的,直接assign
即可
1 |
|
Q2 P1_L0_ALU
使用 搭建一个 32 位六运算 ALU 并提交。具体模块端口定义如下:
模块名:alu
信号名 | 方向 | 描述 |
---|---|---|
A[31:0] | I | 参与ALU计算的第一个值 |
B[31:0] | I | 参与ALU计算的第二个值 |
ALUOp[2:0] | I | ALU功能的选择信号 000: ALU进行加法运算 001: ALU进行减法运算 010: ALU进行与运算 011: ALU进行或运算 100: ALU进行逻辑右移 101: ALU进行算数右移 |
C[31:0] | O | ALU的计算结果 |
模块功能定义如下:
序号 | 功能名称 | 功能描述 |
---|---|---|
1 | 无符号加运算 | C=A+B (A,B无符号) |
2 | 无符号减运算 | C=A-B (A,B无符号) |
3 | 与运算 | C=A&B |
4 | 或运算 | C=A|B |
5 | 逻辑右移 | C=A>>B (A,B无符号) |
6 | 算术右移 | C=A>>>B (A有符号,B无符号) |
需要注意的是算术右移的处理,$signed()
的使用
1 |
|
Q3 P1_L0_EXT
使用 实现 EXT 。EXT为扩展单元,其主要功能是完成将输入到其中的16位数据进行符号扩展、零扩展以及将输入的16位数加载到高位等操作。具体模块端口定义如下:
模块名:ext
信号名 | 方向 | 描述 |
---|---|---|
imm[15:0] | I | 输入EXT内部需要被扩展的16位数据 |
Eop[1:0] | I | 输入数据进行扩展的方式的选择信号 00: 将imm进行符号扩展到32位 01: 将imm进行高位零扩展到32位 10: 将imm加载到高位,低位补0 11: 将imm进行符号扩展后左移两格 |
ext[31:0] | O | 进行扩展之后的输出数据 |
模块功能定义如下:
序号 | 功能名称 | 功能描述 |
---|---|---|
1 | 符号扩展 | 将Input进行符号扩展到32位 |
2 | 零扩展 | 将Input进行高位补零扩展到32位 |
3 | 加载到高位 | 将Input加载到高位,低位补0 |
4 | 符号扩展后左移 | 将Input符号扩展后,左移两位 |
- 使用位拼接运算符处理即可
- 需要注意的是,常数必须指明位宽,否则默认为32位;同时,拼接可以嵌套,但需要用
{}
括起来
1 | `timescale 1ns / 1ps |
Q4 P1_L0_gray
使用 设计一个格雷码计数器。模块端口定义如下:
模块名:gray
信号名 | 方向 | 描述 |
---|---|---|
Clk | I | 时钟信号 |
Reset | I | 同步复位信号 |
En | I | 使能信号 |
Output[2:0] | O | 计数器当前值 |
Overflow | O | 溢出标志位 |
要求实现功能如下:
- 在任意一个时钟上升沿到来的时候,如果复位信号有效,则将计数器清零
- 每个时钟上升沿到来的时候,如果使能信号有效,计数器的值+1
- 在满足1时,即使2的条件满足,也不必执行2
- 计数器初值为0
- 当计数器的值在+1后出现溢出的情况时,将会回到零,同时从发生溢出的这个时钟上升沿开始,溢出标志位将会持续输出1,直到计数器被清零为止(其余情况下溢出标志位必须为0)
关于格雷码
- 对于格雷码,有
- 其余部分就是普通计数器
1 |
|
Q5 P1_L0_表达式状态机
现在,我们需要你用 语言设计一个有限状态机来识别这样一类表达式F:
- 表达式F中只含有数字0-9,加号+,乘号*。
- 表达式F可以按如下的规则产生:
- 单个数字[0-9]是F
- 如果X是F,Y是F,X+Y也是F
- 如果X是F,Y是F,X*Y也是F
模块规格:
模块名:expr
端口名 | 位宽 | 功能 |
---|---|---|
clk | 1 | 接收时钟信号 |
clr | 1 | 接收异步清零信号 |
in[7:0] | 8 | 接收逐个输入的字符,用 ASCII 编码 |
out | 1 | 输出合法性信号 |
- 每个时钟上升沿,状态机从 in 中读入一个ASCII编码的字符。假设读入的第i个字符为,则第n个时钟上升沿时,可以拼出一个字符串:
- 此时若s符合F的定义,那么 out 应输出1,否则输出0
- 如果s当前是空串,out也应输出0。清零后,上面定义的字符串s也应从空串开始计算
- 考虑这几种状态:
- S0: 当前字符串为空
- S1: 当前字符串为F(即合法)
- S2:字符串为
F+
orF*
- S3:字符串非法,如
99
、+9
、++
等(此时只能等待清零信号)
- 注意要异步清零
1 |
|
附加题Q1 P1_L1_BlockChecker
现在需要你用 语言编写一个模拟语句块检查的工具。
为了简化要求,输入由ASCII字母和空格组成。一个或多个连续出现的字母构成一个单词,单词不区分大小写,单词之间由一个或多个空格分隔开。检查工具检查自复位之后的输入中,begin和end是否能够匹配。
匹配规则类似括号匹配:一个begin只能匹配一个end,但是一个匹配的begin必须出现在对应的end之前;允许出现嵌套;最后若出现不能按上述规则匹配的begin或end,则匹配失败。
输入的读取在时钟上升沿进行。
匹配示例:Hello world,begin comPuTer orGANization End。
不匹配示例:eND,beGin study。
模块端口定义如下:
模块名:BlockChecker
信号名 | 方向 | 描述 |
---|---|---|
clk | I | 时钟信号 |
reset | I | 异步复位信号(高电平有效,复位时将输入记录清空) |
in[7:0] | I | 当前输入字符的ASCII码 |
result | O | 当前输入是否能够完成begin和end的匹配 |
- 显然,这题需要统计
begin
和end
单词的数量差, - 同时,需要注意区分
begin
和beginx
(end
和endx
) - 处理组合逻辑和时序逻辑的时候,注意不要让同一个
reg
变量在多个always
块中被赋值,否则会 - state:
- S0: 等待单词读入(此时为空或空格)
- S1: 处理非
begin
和end
的单词 - S2-S5: 判断
begin
- S6: 已读入一个
begin
,读入空格->S7
else ->S1
- S7: 一个
begin
单词 - S8-S9: 判断
end
- S10: 已读入一个
end
,读入空格->S11
else ->S1
- S11: 一个
end
单词 default
1 |
|
课上考试
Q1 P1_L1_dotProduct_2023
请你设计一个向量点乘模块,实现向量的点乘操作。
为了简化题目,我们用两个位宽为 32 的 wire 型变量来表示两个需要点乘的 32 维向量,也就是说,向量任何一个维度的值只能为 0 或 1。你需要将两个向量同一位置相乘并将所有位置的乘积相加输出。
模块端口定义如下:
模块名:dotProduct
信号名 | 方向 | 描述 |
---|---|---|
vector_a[31:0] | input | 需要点乘的向量a |
vector_b[31:0] | input | 需要点乘的向量b |
result[5:0] | output | 点乘结果 |
- 显然,1位二进制数的乘法和
&
操作等价,故答案为vector_a
和vector_b
各位相与之和 - 故此题用
for
循环解决即可,或者ctrl + c v32次(
1 |
|
Q2 P1_L4_coloring_2023
小 B 同学准备对一列格子进行涂色,他想要使用红色,绿色,蓝色三种颜色,但是要求如下:同一颜色不得连续出现三次,红色不得与绿色相连。
我们将在每个周期通过 color 端口输入一个颜色代号:0(红色),1(绿色),2(蓝色),你需要设计 Moore 状态机来检测该涂色序列的合法性,并在检测到不合法的序列之后将输出端口 check 置为 1。
另外,在检测到不合法序列之后,小 B 同学会将最近的一次涂色擦除,重新涂色。
模块端口定义如下:
模块名:coloring
信号名 | 方向 | 描述 |
---|---|---|
clk | I | 时钟信号 |
rst_n | I | 异步复位信号(低电平有效) |
color[1:0] | I | 涂色信号 |
check | O | 当前序列合法性 |
法一:
有限状态机直接设好状态做就行,这里就不给出状态表了因为我没用这种做法
法二:
- 对于这道题,可以发现只需要判断,输入的序列连续两个或三个是什么颜色即可
- 于是可以用四位
state
表示最近两次成功涂色,in
为即将涂上的颜色,这样就可以很简单地进行状态的判断和转移 - 需要注意的是,判断当前序列合法后,才能给
state
更新
低电平有效的异步复位的正确写法:
1 | always @ (posedge clk or negedge rst_n) begin |
1 |
|
Q3 P1_L5_numberNest_2023
题面忘了,先咕了