1、(20分)逻辑化简:
(1)列出真值表
(2)列出其卡诺图
(3)写出Z的最简表达式
答:卡诺图:卡诺图画完后勾1就完事了
提示:约束项的一般形式为:与或式 = 0 (如果不是此种形式,化为此种形式);如此题的BC = 0;或者AB +CD = 0;ABC + CD = 0;等等。BC=0(即B=1,且C=1)对应的格子画X。
2、(5分)ASIC flow 中综合工具的作用是什么?综合的时候需要SDC文件进行约束,请列举3条SDC的语法。
答:ASIC flow 中综合工具的作用是将RTL级的硬件描述语言转换为与特定工艺库相匹配的门级网表,同时进行优化以满足时序、面积和功耗等约束。
综合的时候需要SDC文件进行约束,SDC文件是一种基于Tcl的格式,用于指定设计的时序约束34。SDC文件中的常用时序约束语法有:
create_clock -name <clock_name> -period <clock_period> [get_ports <clock_port>] 用于创建时钟源并指定时钟周期。
set_input_delay -clock <clock_name> <delay_value> [get_ports <input_port>] 用于指定输入端口相对于时钟源的延迟。
set_output_delay -clock <clock_name> <delay_value> [get_ports <output_port>] 用于指定输出端口相对于时钟源的延迟。
set_clock_uncertainty -setup <setup_value> -hold <hold_value> <clock_name> 用于指定时钟源的不确定性,包括建立时间和保持时间。
set_false_path -from [get_ports <source_port>] -to [get_ports <destination_port>] 用于指定不需要进行时序分析的路径。
set_multicycle_path -setup -from [get_clocks <source_clock>] -to [get_clocks <destination_clock>] <cycle_number> 用于指定多周期路径,即源时钟和目标时钟之间有多个周期的时间差。
3、(10分)智力题
(1)2 12 1112 3112 132112 ,下一个数?给理由;
答:第一个数是2,第二个数是12,表示前一个数有1个2;第三个数是1112,表示前一个数有1个1和1个2;以此类推。所以,下一个数是1113122112,表示前一个数有1个1,1个3,2个1和2个2
(2)有一个小偷费劲力气进入到了银行的金库里。在金库里他找到了一百个箱子,每一个箱子里都装满了金币。不过,只有一个箱子里装的是真的金币,剩下的99个箱子里都是假的。真假金币的外形和质感完全一样,任何人都无法通过肉眼分辨出来。它们只有一个区别:真金币每一个重量为101克,而假金币的重量是100克。在金库里有一个电子秤,它可以准确地测量出任何物品的重量,精确到克。但很不幸的是,这个电子秤和银行的报警系统相连接,只要被使用一次就会立刻失效。请问,小偷怎么做才能只使用一次电子秤就找到装着真金币的箱子呢?
答:小偷可以这样做:从第一个箱子里拿出1个金币,从第二个箱子里拿出2个金币,从第三个箱子里拿出3个金币,以此类推,直到从第一百个箱子里拿出100个金币。然后,把所有拿出来的金币放在电子秤上,测量它们的总重量。如果所有的金币都是假的,那么总重量应该是5050克(等于1+2+3+…+100)。如果有一个箱子里是真的金币,那么总重量会比5050克多出一些。这个多出来的部分就是真金币的数量乘以1克。例如,如果第十一个箱子里是真的金币,那么总重量会比5050克多出11克,因为从第十一个箱子里拿出了11个真金币。所以,小偷只要看电子秤上显示的数字减去5050,就能知道哪个箱子里是真的金币了。
4、(10分)选择参与过的任一个项目,简述项目内容以及流程,讲述您在项目中承担的任务,挑一项你认为难的地方并阐述解决方案。
答:优先答ASIC的设计与验证项目,其次是FPGA项目(如基于FPGA的图像处理、天线阵、雷达、加速器等等),其它项目不要答。
5、(5分)用python写一个冒泡排序的函数以及测试程序。
# 定义冒泡排序函数
def bubble_sort(lst):
# 获取列表长度
n = len(lst)
# 遍历列表n-1次
for i in range(n-1):
# 设置一个标志,用于判断是否发生交换
swapped = False
# 遍历未排序的部分
for j in range(n-1-i):
# 如果前一个元素大于后一个元素,交换位置
if lst[j] > lst[j+1]:
lst[j], lst[j+1] = lst[j+1], lst[j]
# 标志设为True,表示发生了交换
swapped = True
# 如果没有发生交换,说明列表已经有序,提前结束循环
if not swapped:
break
# 返回排序后的列表
return lst
# 定义测试程序
# 创建一个乱序的列表
lst = [5, 3, 8, 2, 9, 1, 4, 7, 6]
# 打印原始列表
print("Original list:", lst)
# 调用冒泡排序函数,对列表进行排序
lst = bubble_sort(lst)
# 打印排序后的列表
print("Sorted list:", lst)
结果图
6、(15分)用Verilog 写一个 Round Robin 仲裁器。模块端口如下:
input clock;
input reset_b;
input [N-1:0] request;
input [N-1] lock;
output [N-1] grant; //one-hot
此处的 lock 输入信号,表示请求方收到了仲裁许可,在对应的lock拉低之前,仲裁器不可以开启新的仲裁。(可简单理解为仲裁器占用)
该题要求参数化编程,在模块例化时可调整参数。也即是说你不能写一个固定参数,比如N=8的模块。
参考波形图:
答:
// 功能:
// -1- Round Robin 仲裁器
// -2- 仲裁请求个数N可变
// -3- 加入lock机制(类似握手)
// -4- 复位时的最高优先级定为 0 ,次优先级:1 -> 2 …… -> N-2 -> N-1
`timescale 1ns / 1ps
module RoundRobinArbiter #(
parameter N = 4 //仲裁请求个数
)(
input clock,
input reset_b,
input [N-1:0] request,
input [N-1:0] lock,
output reg [N-1:0] grant//one-hot
);
// 模块内部参数
localparam IDLE = 3'b001;// 复位进入空闲状态,接收并处理系统的初次仲裁请求
localparam WAIT_REQ_GRANT = 3'b010;// 等待后续仲裁请求到来,并进行仲裁
localparam WAIT_LOCK = 3'b100;// 等待LOCK拉低
// 模块内部信号
reg [2:0] R_STATUS; //请求状态
reg [N-1:0] R_MASK; //掩码
wire [N-1:0] W_REQ_MASKED;
assign W_REQ_MASKED = request & R_MASK; //屏蔽低位
always @ (posedge clock)
begin
if(~reset_b)
begin
R_STATUS <= IDLE;
R_MASK <= 0;
grant <= 0;
end
else
begin
case(R_STATUS)
IDLE:
begin
if(|request) //首次仲裁请求,不全为0
begin
R_STATUS <= WAIT_LOCK;
//首先需要找到request中优先级最高的比特位,对优先级最高的比特位给出许可信号。
//这一步可以通过request和它的2的补码按位与。这是因为一个数和它的补码相与,得到的结果是一个独热码,独热码为1的那一位是这个数最低的1
grant <= request & ((~request)+1);
R_MASK <= ~((request & ((~request)+1))-1 | (request & ((~request)+1)));
//得到掩码的方法是,对第一步的许可信号grant-1,再与grant本身相或,相或的结果再取反。
end
else
begin
R_STATUS <= IDLE;
end
end
WAIT_REQ_GRANT://处理后续的仲裁请求
begin
if(|request)
begin
R_STATUS <= WAIT_LOCK;
//在下一轮仲裁中,已经被仲裁许可的比特位变成了最低优先级,而未被仲裁许可的比特位将会被仲裁。
//因此对第一步中给出许可的比特位(假设是第2位)以及它的低比特位进行屏蔽,对request中的第5位到第3位进行保持
//这个操作可以利用掩码111000和request相与实现得到。
if(|(request & R_MASK))//不全为零
begin
grant <= W_REQ_MASKED & ((~W_REQ_MASKED)+1);
R_MASK <= ~((W_REQ_MASKED & ((~W_REQ_MASKED)+1))-1 | (W_REQ_MASKED & ((~W_REQ_MASKED)+1)));
end
else
begin
grant <= request & ((~request)+1);
R_MASK <= ~((request & ((~request)+1))-1 | (request & ((~request)+1)));
end
end
else
begin
R_STATUS <= WAIT_REQ_GRANT;
grant <= 0;
R_MASK <= 0;
end
end
//通过第二步得到第2位到第0位被屏蔽的request_new信号,
//判断request_new是否为全0信号,如果是全0信号,代表此时不存在需要被仲裁的比特位,则返回第一步:找到request中优先级最高的比特位,
//对优先级最高的比特位给出许可信号,然后进行第二步。如果request_new不是全0信号,代表存在未被仲裁的比特位,
//则找到request_new中优先级最高的比特位,对优先级最高的比特位给出许可信号,然后进行第二步。
WAIT_LOCK:
begin
if(|(lock & grant)) //未释放仲裁器
begin
R_STATUS <= WAIT_LOCK;
end
else if(|request) //释放的同时存在仲裁请求
begin
R_STATUS <= WAIT_LOCK;
if(|(request & R_MASK))//不全为零
begin
grant <= W_REQ_MASKED & ((~W_REQ_MASKED)+1);
R_MASK <= ~((W_REQ_MASKED & ((~W_REQ_MASKED)+1))-1 | (W_REQ_MASKED & ((~W_REQ_MASKED)+1)));
end
else
begin
grant <= request & ((~request)+1);
R_MASK <= ~((request & ((~request)+1))-1 | (request & ((~request)+1)));
end
end
else
begin
R_STATUS <= WAIT_REQ_GRANT;
grant <= 0;
R_MASK <= 0;
end
end
default:
begin
R_STATUS <= IDLE;
R_MASK <= 0;
grant <= 0;
end
endcase
end
end
endmodule
测试代码
`timescale 1ns / 1ps
module RoundRobinArbiter_tb;
parameter N = 4; // 可以在测试时调整参数
// 定义测试信号
reg clock;
reg reset_b;
reg [N-1:0] request;
reg [N-1:0] lock;
wire [N-1:0] grant;
// 定义时钟信号
initial clock = 0;
always #10 clock = ~clock;
// 实例化仲裁器模块
RoundRobinArbiter #(
.N(N)
) inst_RoundRobinArbiter (
.clock (clock),
.reset_b (reset_b),
.request (request),
.lock (lock),
.grant (grant)
);
// 定义时钟周期和初始值
initial begin
reset_b <= 1'b0;
request <= 0;
lock <= 0;
end
// 定义请求和锁定信号的变化
initial begin
#20;
reset_b <= 1'b1;
@(posedge clock)
request <= 2;
lock <= 2;
@(posedge clock)
request <= 0;
@(posedge clock)
request <= 5;
lock <= 7;
@(posedge clock)
lock <= 5;
@(posedge clock)
request <= 1;
@(posedge clock)
lock <= 1;
@(posedge clock)
request <= 0;
@(posedge clock)
lock <= 0;
#1000 $stop; // 测试结束
end
// 显示测试结果和波形图
initial begin
$monitor("Time=%t, clock=%b, reset_b=%b, request=%b, lock=%b, grant=%b",
$time, clock, reset_b, request, lock, grant);
$dumpfile("RoundRobinArbiter_tb.vcd");
$dumpvars(0,RoundRobinArbiter_tb);
end
endmodule
结果:
如果对波形图无法理解可以看此博文
https://blog.csdn.net/m0_49540263/article/details/114967443
7、(15分)关于DMA寄存器配置,DMA寄存器(地址 0x81050010)表:
Type 表示读写类型。Reset 表示复位值。
写一个C函数 void dma_driver(void),按步骤完成以下需求:
分配DMA所需的源地址(0x30)
分配DMA所需的目的地址(0x300)
设置传输128 Byte 数据
开始DMA传输
等待DMA传输结束
答:
// 假设有以下宏定义
#define DMA_REG 0x81050010 // DMA控制寄存器的地址
#define DMA_SRC_ADDR 0x30 // DMA源地址
#define DMA_DST_ADDR 0x300 // DMA目的地址
#define DMA_SIZE 128 // DMA传输大小
#define DMA_START 1 // DMA开始传输的标志位
// 定义C函数 void dma_driver(void)
void dma_driver(void) {
// 定义一个指向DMA控制寄存器的指针
volatile uint32_t *dma_reg = (volatile uint32_t *)DMA_REG;
// 清空DMA控制寄存器的值
*dma_reg = 0;
// 设置DMA源地址,目的地址和传输大小
*dma_reg |= (DMA_SRC_ADDR << 2) | (DMA_DST_ADDR << 13) | (DMA_SIZE << 24);
// 开始DMA传输
*dma_reg |= DMA_START;
// 等待DMA传输结束
while (*dma_reg & DMA_START) {
// 可以在这里做一些其他的事情,比如打印日志或者检查错误
// printf("Waiting for DMA to finish...\n");
// check_error();
}
}
8、(20分)二阶带通滤波器,利用RC组件搭建,通带范围 1kHz~30kHz ,两个电阻 R 均为10kΩ ,问两个电容容值多少?
答:第一步首得知道二阶带通(RC)滤波器的电路长啥样,高、低通组合一下就是带通,自己思考一下高、低通组合:如串联或并联,会得到带通还是带组?
电路图:
这个一看就是总传递函数=A1*A2(模电二阶有源或无源滤波器绝对有)
然后化简
根据推导得到的表达式,对于 jwRC2 ,这一项,当 w 趋于无穷大时,uo/ui 趋于零。那么高频的临界点就是 wRC2 = 1+2C2/C1;(此时忽略低频项1/jwRC1)
同理,对于低频项 1 /jwRC1, w 趋于无穷小时,uo/ui 趋于零 ,那么低频的临界点就是 1/wRC1 = 1+2C2/C1;然后解二元一次方程两个电容就被解出来了
这里提供一种更简单方法:
二阶带通滤波器的中心频率 f0 和品质因数 Q 可以用下面的公式计算:
已知 R1 = R2 = 10kΩ,f0 = (1kHz + 30kHz) / 2 = 15.5kHz,Q = f0 / (30kHz - 1kHz) = 0.54,代入上面的公式,可以求得:
这是一个二元一次方程组,可以用任意方法求解,例如消元法或代入法。为了方便起见,我们假设 C1 和 C2 的值相近,那么可以近似地认为 C1 = C2 = 3.45nF。这样就得到了两个电容的容值。当然,也可以选择其他的电容值,只要满足上面的方程组即可。
评论 (0)