2022乐鑫数字芯片提前批笔试

  • Post author:
  • Post category:其他


我感觉乐鑫的笔试真的好难啊!!!

单项选择(3 分)


1.以下关于 System Verilog 的描述, 正确的是

A sv 中可以用 logic 代替 Verilog 中的 wire 和 reg 类型

B sv 中, 定义成 reg 的信号会被综合成触发器

C sv 中的 function 语言不可被综合

D 其他都不正确

E sv 是提供给验证使用的, 因此其不能被综合

解:

Ainout型端口只能用wire

B不完全组合逻辑中reg变量也可以对应为锁存器

E 可综合


task和function:

共同点:

1.verilog中task和function是相同的。

2.将复杂代码分割成小段落,便于理解和调用,简化程序,功能单一;

3.端口参数默认都是输入,除非声明其他类型;

4.数据类型默认是logic,除非声明为其他类型;

5.可以存在多个语句,不用begin…end做开始结尾;

6.wire类型数据不可以在端口使用;

7.通过引用、值、名称、位置传递参数值;

不同点:

sv中增加的使用:在静态task和function中声明动态变量,以及在动态task和function中声明静态变量。

1.function不能消耗仿真时间;task可以消耗仿真时间;比如function不能带有#100的时延语句、不能有@(posedge clk)、不能有wait(ready)的阻塞语句。

2.function不能调用task;task可以调用function或task;注意:sv中允许function调用task,但只能在fork…join_none生成的线程中调用。

3.function可以使用void表示不返回结果;task不使用void表示不返回结果;

4.function只能返回一个值;注意:task无返回值;verilog fucntion必须要有一个返回值;sv可以使用void’(call_function(params))避免返回值。


2.UVM 层次化结构中, 最顶层的部件类型是?

A uvm_test

B uvm_root

C uvm_top

D uvm_component

解:B


知识点:常用的uvm_component:

Uvm_driver:所有driver都要派生uvm_driver。Driver的功能主要就是向sequencer索要sequence_item(transaction),并把sequence_item里的信息驱动到DUT的接口上。相当于完成了transaction级别到DUT能够接受的pin级别信息的转变。

Uvm_monior:所有monitor都要派生子uvm_monitor。Monitor从DUT的pin上接收数据,并且把接收到的数据转换成transaction级别的sequence_item,并把转换后的数据发送给scoreboard,供scoreboard比较。

Uvm_sequencer:所以的sequencer都要派生自uvm_sequencer。其功能1就是组织管理sequence,当driver要求数据时,他就把sequence生成sequence_item转发给driver。

Uvm_scoreboard:一般的scoreboard都要派生自uvm_scoreboard。其功能就是比较reference model和monitor分别发送来的数据,根据比较结果判断DUT是否正确。

Reference model:reference model直接派生自uvm_component。其作用就是模仿DUT,完成与DUT相同的功能,可以直接使用systemverilog的特性,或者可以通过DPI等接口调用其它语言来完成与DUT相同功能。

Uvm_agent:所以agent都要派生自uvm_agent。只是把driver和monitor封装在一起,根据参数来决定是只实例化monitor还是要实例化driver和monitor。

Uvm_env:所有env都要派生自uvm_env。把验证平台固定不变的component封装在一起。这样在要跑不同case时,只要在case中实例化一个env就可以。

Uvm_test:所有的case都要派生自uvm_test。Case之间差异很大,所以从uvm_test派生出来的类各不同。任何一个派生的case都要实例化env,只有这样才能正常传数。


3.数字信号上采样时, 一般需要添加什么样的滤波器, 完成功能为?

A 高通, 抗混叠滤波

B 低通, 抗周期延拓

C 低通, 抗混叠滤波

D 高通, 抗周期延拓

解: B

过采样技术的低通滤波器要同时完成量化噪声的滤除和降采样时抗混叠滤波的功能。


数字信号的上采样和下采样



https://zhuanlan.zhihu.com/p/356453685



http://blog.chinaunix.net/uid-30104746-id-5140178.html



4.下列不属于异步总线的是?

A SPI

B USB

C UART

D IIC

解:ABD

(1) SPI——

同步通信

;串行通信;全双工;主从通信(某一时刻可以出现多个从机,但只能存在一个主机,主机通过片选线来确定要通信的从机)。

(2) USB——

异步通信

;通用串行总线。

(3) UART——Universal Asynchronous Receiver/Transmitter,通用异步收发器;

异步通信

;串行通信;全双工;对等总线,没有仲裁机制,所以只能挂载两个同时收发数据的设备,双方都可以发送和接收。

(4) I2C——

同步通信

;串行通信;半双工;主从通信(总线上支持多个主机和多个从机,总线上任何能够进行发送/接收数据的设备都可以占领总线。当然,任意时间点上只能存在一个主控。多主控,主器件同时争夺总线控制权时,可仲裁)。

在这里插入图片描述


通讯协议介绍


5.() 电路的逻辑功能特点是, 任意时刻的输出仅仅取决于该时刻的输入, 与电路原来的状

态无关

A 静态逻辑

B 组合逻辑

C 动态逻辑

D 时序逻辑

解:B


静态逻辑

电路中靠稳定的输入信号使MOS晶体管保持导通或截止状态,从而维持稳定的输出状态。输入信号存在,对应的输出状态存在;只要不断电,输出信息可以长久保持;


动态逻辑

电路中利用电容的存储效应来保存信息,即使输入信号不存在,输出状态也可以保持,但由于泄漏电流的存在,信息不能长期保持;


6.在芯片设计流程当中, 通常会进行后仿真(post-simulation) ,关于后仿的作用, 以下说法

不正确的是

A 抽检 netlist 是否和 RTL 功能一致

B 抽检电路中是否出现有害的 glitch

C 抽检时序是否有违规

D 抽检电路中是否存在亚稳态

解:B(我觉得都对)

后仿作用:

检查时序约束(SDC)的完备性——防止约束的遗漏

检查异步电路的时序——STA工具无能为力

检查网表的完备性——防止综合、布局布线过程中的意外

为后续流程如功耗(Power)分析、压降(IR Drop)分析提供波形——更准确

测试向量的仿真——只有门级网表才包含扫描链


7.以下关于异步处理正确的是

A 信号经过两级触发器即可完成异步信号的传递‘

B 只要信号传递的两端时钟频率不相等, 即认为是异步信号

C 异步复位信号需要经过同步处理后再使用是安全的

D 异步 FIFO 中使用格雷码传递异步计数器可以保证每一拍传递的数据都是准确的

解:C

高赞又看到了老李这个神


https://www.zhihu.com/question/290661321


至于为什么

选择格雷码进行传输,我们来看格雷码传输失效的情况:

格雷码传输失效,只有一位同步出错,此时地址没有跳变。如果是写地址同步失效,用这个错误的写地址在读时钟域进行空判断时不会出错,最多是让空标志在FIFO不是真正空的时候产生,而不会产生空读的情况。格雷码保证的是同步后的读写地址即使在出错的情况下依然能够保证FIFO功能的正确性。


8.关于跨时钟域电路的设计, 以下说法正确的是

A 单 bit 信号经两级 D 触发器同步后即可进行跨时钟域传递

B 采用单一时钟的电路不会产生亚稳态

C 异步 FIFO 的两个时钟频率相同也可以正常工作

D 跨时钟域电路当中的亚稳态无法消除

解:C(为什么选D?有疑问)一般认为D是错的,但我感觉是可以消除亚稳态的


9.衡量数字通信系统传输质量的指标是

A 信噪比

B 噪声功率

C 语音清晰度

D 误码率

解:D传输质量不是信号质量


10.以下代码片段实现的电路功能是

Input [3:0] in;

output [3:0] out;

wire [3:0] a,b;

assign a=in<<1;

assign b=in>>3;

assign out=a|b;

A 对输入信号 in 先右移 3 位, 再左移 1 位

B 对输入信号 in 循环左移 1 位

C 对输入信号 in 循环右移 3 位

D 对输入信号 in 先左移 1 位,再右移 3 位

解:B(bc都对)

填空(4 分)

1.verilog 当中 a=4’b10x1;b=4’b10x1;那么逻辑表达式 a

b 为___x___ a

=b 为_____1___


sv语法逻辑===、!==、==、!=


2.4bit 的信号输入和 8bit 的信号输入的乘法器内部计算输出信号至少需要___12___ bit 的位宽

3.通常情况下, 芯片工作温度较____低____, 工作电压较____高___ , 速度最快。

4.以下代码的打印输出是______0____

always@(posedge clk)

begin

a=0;

a<=1;

$display(“%0b”,a);

end

解:由于非阻塞赋值只能在周期结束生效,而display语句打印的是当前值,所以结果是a=0。

%b使用固定宽度显示,以适应所显示表达式的最大可能值。 %0b显示最小宽度,禁止任何前导0或间隔。

5.全部使用组合逻辑实现 A, B, C 的运算实现|A*(B+C)|^2 共需使用___2____ 个乘法器与___1____个加法器

解:wire data1,data_out;

assign data1 = A*(B+C); (1乘1加)

assign data_out = data1*data1;(1乘)

有的答案是6乘5加,答案待确定

问答(25 分)

1.

在这里插入图片描述

endmodule

解:

a、

`timescale 1ns / 10ps
module tb();
parameter clk_cyc = 2;
reg wave;

initial begin
       wave = 0;
   #2  wave = 1;
   #3  wave = 0;
   #5  wave = 1;
   #5  wave = 0;
   #1  wave = 1;
   #1  wave = 0;
   #5  wave = 1;
   #1  wave = 0;
   #4  wave = 1;
   #3  wave = 0;  
end

endmodule

b、

`timescale 1ns / 10ps
module wire_a(
    input in,
    output  out
);

reg out_reg;
//assign out = #5 in; (非法)
always@(*)begin
	out <= #5 in;
end
assign out =  out_reg;
endmodule


verilog几种添加仿真延迟的方法;


2.使用 v/sv 编写如下功能模块,求输入信号序列 din 在 din_vld 为高电平的时间段内的次小值与次小值出现的次数

接口信号如下

module sec_min(

input clk,//时钟

input rst_n,//复位

input [9:0] din, //10bit 无符号数

input din_vld, //输入数据有效信号

output [9:0] dout, //次小值

ouput [8:0] cnt //次小值出现的次数。溢出时重新计数

);

我写的:

module sec_min(
    input            clk,//时钟
    input            rst_n,//复位
    input      [9:0] din, //10bit 无符号数
    input            din_vld, //输入数据有效信号
    output     [9:0] dout, //次小值
    output reg [8:0] cnt //次小值出现的次数。溢出时重新计数
);

reg [9:0] min1,min2;
reg [9:0] data_new;
reg [1:0] vld_delay;

wire      pulse1;
wire      pulse2;

//捕获din_vld为高电平的前两个上升沿,给min1(最小值)和min2(次小值)赋初值
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        vld_delay <= 2'b0;
    else 
        vld_delay <= {vld_delay[0],din_vld};
end

assign pulse1 = ~vld_delay[0] & din_vld;  
assign pulse2 = ~vld_delay[1] & din_vld;

//捕获din_vld下降沿
reg vld_dff;

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        vld_dff <= 1'b0;
    else 
        vld_dff <= din_vld;
end

assign vld_dff = ~vld_delay & din_vld;
assign dout = vld_dff?min2:1'b0;

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        min1 <= 'b0;
        min2 <= 'b0;
        data_new <= 'b0;
    end
    else begin
        if(din_vld)begin
            data_new <= din;
            if(pulse1)
                min1 <= data_new;
            else if(pulse2)&&(data_new > min1)begin
                min2 <= data_new;
            end
            else if(pulse2)&&(data_new < min1)begin
                min2 <= min1;
                min1 <= data_new;
                cnt <= 1'b1; 
            end
            else if(pulse2)&&(data_new == min1)begin
                min2 <= data_new;
                min1 <= min1;
                cnt <= 1'b2; 
            end
            else if(data_new == min2)begin //min1<min2=data_new
                 cnt <= cnt + 1'b1;
                 min1 <= min1;
                 min2 <= min2;
            end
            else if(data_new > min1) && (data_new < min2)begin//min1<data_new<min2
                 min1 <= min1;
                 min2 <= data_new;
                 cnt <= 1'b1;
            end
            else if(data_new < min1) && (data_new < min2)begin//data_new<min1<min2//当新值比最小值小的时候,就要将min_cnt赋值给sub_cnt,这里写错了
                 min1 <= data_new;
                 min2 <= min1; //将min1赋给min2
                 cnt <=  cnt;
            end
            else begin //min1<min2<data_new
                 cnt <= cnt;
                 min1 <= min1;
                 min2 <= min2;
            end
            end
        end
    end
end

endmodule

别人写的:

我感觉差不多,有空仿真一下

module sec_min(
    input   clk,                //时钟信号
    input   rst_n,              //复位信号
    input   [9:0]   din,        //10bit无符号数
    input   din_vld,            //输入数据有效信号
    output  [9:0]   dout,       //次小值
    output  [8:0]   cnt          //次小值出现的次数,溢出时重新计数
);

reg    [9:0]    min_data;
reg    [9:0]    sub_data;
reg    [9:0]    data_reg;
reg    [1:0]    data_cnt;
reg    [8:0]    sub_cnt;
reg    [8:0]    min_cnt;

//寄存一拍
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        data_reg<='d0;
    end
    else if(din_vld) begin
        data_reg<=din;
    end
    else begin
        data_reg<='d0;
    end
end


//计数器,区分第一个数据,第二个数据,和其他的数据
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        data_cnt<='d0;
    end
    else if(din_vld) begin
        if(data_cnt<'d3)begin
            data_cnt<=data_cnt+1;
        end
        else begin
            data_cnt<='d3;
        end
    end
    else begin
        data_cnt<='d0;
    end
end


//分情况讨论,第一个数据来的时候,将第一个数据给最小值和次小值;在第二个数据来的时候,分情况讨论;在第三个及后面的数据来的时候,分情况讨论。
always@(posedge clk or negedge rst_n )begin
    if(!rst_n)begin
        min_data<='d0;
        sub_data<='d0;
    end
    if(din_vld) begin
        min_data<=data_reg;
        sub_data<=data_reg;
        if(data_cnt=='d1)begin
            min_data<=data_reg;
            sub_data<=data_reg;
        end
        else if(data_cnt=='d2)begin
            if(data_reg<min_data)begin
                min_data<=data_reg;
                sub_data<=min_data;
            end
            else begin
                min_data<=min_data;
                sub_data<=data_reg;
            end
        end
        else if(data_cnt=='d3) begin
            if(data_reg<min_data)begin
                min_data<=data_reg;
                sub_data<=min_data;
            end
            else if(data_reg==min_data)begin
                min_data<=min_data;
                sub_data<=sub_data;
            end
            else if(data_reg<=sub_data)begin
                min_data<=min_data;
                sub_data<=data_reg;
            end
            else begin
                min_data<=min_data;
                sub_data<=sub_data;
            end
        end        
    end
    else begin
        min_data<='d0;
        sub_data<='d0;
    end 
end


//根据数据来的顺序和数值来进行次小值和最小值出现次数的计算
//然后分情况讨论,当新值比最小值小的时候,就要将min_cnt赋值给sub_cnt
//其他情况比较容易想到,有问题请留言讨论
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        sub_cnt<='d0;
        min_cnt<='d0;
    end
    else if(din_vld) begin
        if(data_cnt==1)begin
            sub_cnt<='d1;
            min_cnt<='d1;
        end
        else if(data_cnt==2||data_cnt==3)
        if(data_reg<min_data)begin
            sub_cnt<=min_cnt;
            min_cnt<='d1;
        end
        else if (data_reg==min_data)begin
            sub_cnt<=sub_cnt;
            min_cnt<=min_cnt+1;
        end
        else if(data_reg<sub_data)begin
            sub_cnt<='d1;
            min_cnt<=min_cnt;
        end
        else if(data_reg==sub_data) begin
            sub_cnt<=sub_cnt+1;
            min_cnt<=min_cnt;
        end
        else begin
            sub_cnt<=sub_cnt;
            min_cnt<=min_cnt;
        end
    end
    else begin
        sub_cnt<='d0;
        min_cnt<='d0;
    end
end

//进行输出
assign    dout=sub_data;
assign     cnt=sub_cnt;

endmodule



版权声明:本文为weixin_44072819原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。