【华为笔试真题】第一篇 (01~10)

【华为笔试真题】第一篇 (01~10)

1.进制转换
在这里插入图片描述
D
除基逆取余,乘基顺取整。

2.状态机和编码方式
在这里插入图片描述
C
根据编码方式的不同,状态机需要的变量数量也不同(例如:格雷码只需2位,独热码需要3位),此处问最少的变量数,即为C。
用Verilog描述一个简单状态机,其功能是每次只能输入1元硬币,输入3元时出可乐:

module simple_fsm(   //finite state machine
input wire sys_clk,
input wire sys_rst_n, //全局复位信号
input wire pi_money, //投币信号,不投币(0),投币(1)
output reg po_cola //出可乐(1),不出可乐(0)
};
//使用独热码
parameter IDLE =3'b001;
parameter ONE  =3'b010;
parameter TWO  =3'b100;

reg [2:0] state;

always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n ==1'b0) state<=IDLE;
else
    case (state)
        IDLE: if(pi_money==1'b1) state<=ONE;
                  else state<=IDLE;
        ONE: if(pi_money==1'b1) state<=TWO;
                  else state<=ONE;
        TWO: if(pi_money==1'b1) state<=IDLE;
                  else state<=TWO; 
        default: state<=IDLE;
    endcase
//第二段状态机,描述当前状态state和输入pi_money如何影响po_cola的输出
always@(posedge sys_clk or negedge sys_rst_n) 
if(sys_rst_n == 1'b0) po_cola<=1'b0;
else if((state == TWO)&&(pi_money ==1'b1))  po_cola<=1'b1;
else po_cola<=1'b0;

endmodule

该状态机由独热码进行描述,独热编码即 One-Hot 编码,又称一位有效编码,其方法是使用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候,其中只有一位有效。
自然状态码为:000,001,010,011,100,101
独热编码为:000001,000010,000100,001000,010000,100000

使用变量最少的方法为格雷码:在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code),另外由于最大数与最小数之间也仅一位数不同,即“首尾相连”,因此又称循环码或反射码。 在数字系统中,常要求代码按一定顺序变化。例如,按自然数递增计数,若采用8421码,则数0111变到1000时四位均要变化,而在实际电路中,4位的变化不可能绝对同时发生,则计数中可能出现短暂的其它代码(1100、1111等)。在特定情况下可能导致电路状态错误或输入错误。使用格雷码可以避免这种错误。格雷码有多种编码形式。
在这里插入图片描述

3.存储器的分类
在这里插入图片描述
C
ROM在制作过程中被编程或烧录,在断电后不会丢失数据。

4.Verilog语法中的操作符
在这里插入图片描述
C
&+一个操作数:归约与,&m是将m中所有比特相与,最后的结果为1bit。例:&4‘b1111 = 1&1&1&1 = 1’b1,&4’b1101 = 1&1&0&1 = 1’b0。
&+两个操作数:按位与,m&n是将m的每个比特与n的相应比特相与,在运算的时候要保证m和n的比特数相等,最后的结果和m(n)的比特数相同。例:4’b1010&4’b0101 = 4’b0000,4’b1101&4’b1111= 4’b1101。
&&+两个操作数:判断两个操作数是否都为真,m &&n是判断m和n是否都为真,最后的结果只有1bit,如果都为真则输出1‘b1,如果不都为真则输出1’b0。

5.对组合逻辑的认识
在这里插入图片描述
状态机(Finite State Machine),一般使用状态转移图描述状态机,而不可用状态机描述组合逻辑电路。
在这里插入图片描述
6.对时序逻辑的认识
在这里插入图片描述
C
A、B、D选项都是和状态机相关的描述。状态机主要分为Moore型状态机和Mealy型状态机两大类,其共同点是:状态的跳转都和当前状态与输入有关。主要的区别在于输出:Moore型状态机的输出只和当前状态有关而与输入无关;而Mealy型状态机的输出不仅和当前状态有关还与输入有关。
状态机不仅可以由状态转移图来描述,还可以用状态转移表来描述,但是状态转移图的表述更加直C观,且更有利于RTL代码的编写。
时序电路一定需要由时钟沿触发的触发器来保存数据,所以不能没有时钟,C选项错误。

7.竞争冒险的认识
在这里插入图片描述
A
什么是竞争-冒险现象?:在组合逻辑电路中我们将门电路两个输入信号同时向相反的逻辑电平跳变(一个从1变为0,另一个从0变为1)的现象称为竞争。由于竞争而在电路输出端可能产生尖峰脉冲的现象(毛刺)就称为竞争-冒险。
电路中是否会存在竞争-冒险现象?:在输入变量每次只有一个改变状态的简单情况下,可以通过逻辑函数式判断组合逻辑是否存在竞争-冒险现象。如果输出端电路的两个输入信号A和A’是输入变量A经过两个不同的传输途径而来的,那么的那个输入变量A的状态发生突变时输出端便有可能产生尖峰脉冲。因此,只要输出端的逻辑函数在一定条件下化简成Y = A+ A’ 或Y = A* A’ 则可判定存在竞争-冒险现象。
如何消除竞争-冒险现象?:
1)输出端接入滤波电容
在这里插入图片描述

2)引入选通脉冲或使用时序逻辑电路(添加sclk)
在这里插入图片描述

3)修改逻辑设计,增加冗余项
竞争-冒险现象主要是由两个输入信号同时向相反的逻辑电平跳变产生的(而不是由于输入信号的尖峰干扰),因此屏蔽输入信号的尖峰干扰和前级加电阻并不可以消除经过组合逻辑后输出的毛刺。正确的方法为在输出端接入滤波电容。

8.基本时序逻辑电路
在这里插入图片描述
A
"MUX 2:1"为一个简单的二选一多路选择器,冒号左边表示输入数据通道的个数,右边的数表示输出数据通道的个数。所以题目中的MUX 2019:1表示的是2019选1多路选择器,即有2019路数据输入通道,通过sel选通信号从2019路输入中选通一路输出。
扩展:使用Verilog代码描述二选一多路选择器
方法一:always中if-else实现方法

module mux2_1(
input wire in1,
input wire in2,
input wire sel,
output reg out);

always@(*)
if(sel==1'b1) out=in1;
else out=in2;

endmodule

根据上述代码,RTL的综合结果为:
在这里插入图片描述
方法二:always中case实现方法

module mux2_1(
input wire in1,
input wire in2,
input wire sel,
output reg out);

always@(*)
case(sel)
    1'b1:out=in1;
    1'b0:out=in2;
    default:out=in1;
endcase
endmodule

根据上述代码,RTL的综合结果为:
在这里插入图片描述
方法三:assign中三目运算符

module mux2_1(
input wire in1,
input wire in2,
input wire sel,
output reg out);

assign out=(sel==1'b1)?in1:in2;

endmodule

根据上述代码,RTL的综合结果为:
在这里插入图片描述

9.建立时间和保持时间
在这里插入图片描述
D
建立时间(Set Up Time,简写为Tsu或Ts):是指在触发器的时钟信号上升沿到来以前,数据稳定不变的时间。
建立时间的门限(为了和建立时间区别开,所以简写为T_setup):时钟沿来到之前数据必须保持稳定的最小时间,芯片选定即决定,和制作工艺有关。
保持时间(Hold Time,简写为Th):是指在触发器的时钟信号上升沿到来以后,数据稳定不变的时间,如果保持时间不够,数据同样不能被稳定的打入触发器,Th就是指这个最小的保持时间。
保持时间的门限(为了和保持时间区别开,所以简写为T_hold):时钟沿来到之后数据必须保持稳定的最小时间,芯片选定即决定,和制作工艺有关。
在这里插入图片描述
如果我们想让系统中的时钟沿能够正确的采集到数据,那么需要建立时间的余量/裕量(Setup Slack,简写为Sslack) = 建立时间(Ts) - 建立时间的门限(T_setup) ≥ 0,且保持时间的余量/裕量(Hold Slack,简写为Hslack) = 保持时间(Th) - 保持时间的门限(T_hold) ≥ 0,采集到的数据最准确的地方就是在满足建立保持时间的情况下时钟沿采集到数据的中间位置。

10.同步时序电路
在这里插入图片描述
B
电路设计可分类为同步电路设计和异步电路设计。同步电路设计利用时钟脉冲使其子系统同步运作,而异步电路设计不使用时钟脉冲做同步,其子系统是使用特殊的“开始”和“完成”信号(握手信号)使之同步。在同步电路设计中一般采用D触发器,异步电路设计中一般采用Latch。

  • 31
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
1. 虚函数是可以[New一个对象的时候要根据虚函数的函数体来填虚表;而内联函数没有函数体,只是在预编译阶段展开]内联的,这样就可以减少函数调用的开销,提高效率(错误) 2. 一个类里可以同时存在[同一个类里无论什么函数都不能函数名和参数完全一样]参数和函数名都相同的虚函数与静态函数(错误) 3. 父类的析构函数是非虚的,但是子类的析构函数是虚的,delete子类指针(指向该子类对象)[特殊情况,参见题5],会调用父类的析构函数(正确)//任何情况下删除子类都会调用到父类的析构函数 4.对于下面的类CA,sizeof(CA) = _B_: A. 4 B. 8 C. 12 D. 16 class CA { public: CA(); virtual ~CA(); //因为有虚函数,所以会有4个字节的虚表指针 private: int m_iTime; //成员变量4个字节 public: int GetTime(); int SetTime(int iTime); }; 5.下面这段程序,打印结果是_A_: A. 1 B. 2 C. 3 D. 以上都不对 int g_iCount = 0; class CParent { public: CParent() {} ~CParent() {g_iCount += 1;} }; class CSon : public CParent { public: CSon() {} ~CSon() {g_iCount += 2;} }; main() { CParent* p = new CSon(); delete p[由于p被声明成父类指针,并且父类和子类的析构函数都非虚,因此delete操作只能根据p指针声明的类型来调用父类的析构函数]; std::cout << g_iCount << std::endl; } 6.请问下面这段程序的输出结果是_A_: A. 2,1, B. 2,2, C. 1,1, D. 1,2, class CParent { public: CParent() {} virtual ~CParent() {} public: virtual void Print() { std::cout << "1,"; }; }; class CSon : public CParent { public: CSon() {}; virtual ~CSon() {}; public: void Print() { std::cout << "2,"; }; }; void Test1(CParent& oParent[这里是引用了一个外部对象,该对象的虚表不会发生变化]) {oParent.Print();} void Test2(CParent oParent[这里会在栈空间内重新构造一个CParent类的对象,如果传入实参的类型与CParent不同则虚表会发生变化]) {oParent.Print();} main() { CSon * p = new CSon(); Test1(*p); //这里只是一个引用 Test2(*p); //这里会在栈空间重新构造Cparent类对象 delete p; } 7.请问下面这段程序的输出结果是_D_: A. 2,1, B. 2,2, C. 1,1, D. 1,2, class CParent { public: CParent() {} virtual ~CParent() {} public: void Print(){ std::cout << "1," ; }; }; class CSon : public CParent { public: CSon() {} virtual ~CSon() {} public: void Print(){ std::cout << "2,"; }; }; main() { CSon oSon; CParent * pParent = &oSon; CSon * pSon = &oSon; pParent->Print(); pSon->Print();[由于父类和子类的Print函数都非虚,所以根据指针类型决定调用关系] } 8.请问下面这段程序的输出结果是_C_: A. 2,1, B. 2,2, C. 1,2, D. 1,1, class CParent { public: CParent() {Print();} virtual ~CParent() {} public: virtual void Print(){ std::cout << "1,"; } }; class CSon : public CParent { public: CSon() {Print();} virtual ~CSon() {} public: void Print(){ std::cout << "2,"; } }; main() { CParent * pParent = new CSon()[类的构造过程遵循压栈原则,构造过程中虚表尚未建立成功,是静态调用虚函数]; delete pParent; } 9.请问下面这段程序的输出结果是_D_: A. 2,2, B. 2, C. 输出结果不确定 D. 以上都不对 class CParent { public: CParent() {Print();[构造子类对象时调用到父类的构造函数,但父类的Print函数是纯虚的,没有实现,所以这里的调用不成功,编译会出错]} virtual ~CParent() {} public: virtual void Print() = 0; }; class CSon : public CParent { public: CSon() {Print();} virtual ~CSon() {} public: void Print() { std::cout << "2,"; }; }; main() { CParent * pParent = new CSon(); delete pParent; } 10.请仔细阅读以下程序: class Base { public: virtual bool operator == (int iValue) { std::cout << "I am Base class !" << std::endl; return true; } virtual ~Base(){} }; class Derive: public Base { public: virtual bool operator == (int iValue) { std::cout << "I am Derive class !" << std::endl; return true; } virtual ~Derive(){} }; int main() { Derive derive; Base* pBase = &derive; Derive* pDerive = &derive; *pBase == 0; *pDerive == 0;[重载操作符声明为virtual使操作符产生多态性] return 0; } 程序的输出结果是_B_: A、I am Base class ! I am base class ! B、I am Derive class ! I am Derive class ! C、I am base class ! I am Derive class ! D、I am Derive class ! I am Base class !
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值