2021乐鑫提前批笔试

1、以下代码综合出来的D触发器的D端逻辑表达式为:

always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		q <= 1'b0;
	end
	else if(set) begin
		q <= 1'b1;
	end
	else if(wr) begin
		q <= wdata;
	end
end

这个题的正确答案应该是:set | wr & wr_data | ~wr & q
个人分析:当置位为1时,q输出为1,当wr为1时,q输出为wr_data,当都不为1时,q输出保持。

2、关于跨时钟域电路的设计,以下说法正确的是:
A : 信号经过两级D触发器同步后即可进行跨时钟域传递
B : 跨时钟域电路存在亚稳态风险,最好避免使用
C : 采用单一时钟的电路也可能产生亚稳态
D : 跨时钟域电路一定存在亚稳态

个人觉得这个题应该选C
首先A,多比特信号不能用两级触发器进行跨时钟域吧
B设计需要两个时钟域的数据进行交互处理,肯定要进行跨时钟域电路
D跨时钟域电路就是尽可能的减少亚稳态的出现的概率

3、若要将一异或非门当做反相器(非门)使用,则输入端A、B端的连接方式是:
A : A或B中有一个接“0”
B : A和B并联使用
C : 不能实现
D : A或B中有一个接“1”

个人选择A
A固定为0时,当B为1,异或为1,然后再非就为0;当B为0时,先异或为1,然后再非就是1,从而实现了非门
D会成为与门

4、欲产生序列信号11010111,则至少需要()级触发器。
A 3
B 4
C 5
D 2
个人选择A
因为检测8个信号,用2^3,就可以实现8个状态

在这里插入图片描述5、ModuleA / ModuleB用的是同一个clock,clock频率80Mhz,ModuleA和ModuleB同时启动。ModuleA产生如下周期性的burst数据传递给moduleB,一共产生8次burst。burst rate:1280Mbit/s.burst持续时间1us,burst内部速率均匀,burst周期5us。剩下的4us没有数据。
ModuleB收到启动信号后,需要花10us做初始化,所以先把moduleA的数据缓存在module内部的同步FIFO中,同步FIFO的位宽32bits,初始化结束后,ModuleB以640Mbit/s的均匀速率从FIFO中读取数据。在满足功能的前提下,为了节省电路面积,要求FIFOsize越小越好,以下4个选项FIFO选择哪个更好。

A : 96
B : 128
C : 160
D : 64

个人选择:B
考虑最大数据情况,在ModuleB启动的10us内,ModuleA一直在传输数据,一共2us有效数据,需要存储 1280Mbit/s * 2us = 2560 bit;在第11us,ModuleA传输数据 1280Mbit/s * 1us = 1280 bit,ModuleB读取 640 Mbit/s * 1us = 640 bit,需要存储 1280 - 640 = 640 bit,此时共需存储 2560 + 640 = 3200 bit。
考虑读取,前15us共写入 3 * 1280=3840,读取 5*640=3200,需要存储640。
综合考虑,最大需要存3200bit,深度需要 3200 / 32 = 100,选A的128较为合适。

6、以下方法哪些是进行面积优化的()
A : 逻辑优化
B : 串并化
C : 寄存器配平
D : 流水线设计
E : 资源共享
F : 关键路径优化

个人选择:ABE
面积优化,提高资源利用率以降低功耗要求:串行化,资源共享,逻辑优化;
速度优化,提高运行速度:流水线设计,寄存器配平,关键路径优化。
7、可综合的Verilog语法包括()
A : for
B : wait
C : time
D : always
E : initial
F : generate
G : assign

个人选择 : ADFG

8、在异步设计中对跨时钟处理的信号,功能验证时一般需要考虑以下哪些因素()
A : 信号变化的最小宽度
B : 信号高电平有效还是低电平有效
C : 相位和抖动
D : 时钟频率

个人选择: ABD
重点是功能验证
9、 在高速系统设计中,下列哪种优化方案可以提供系统的工作频率()
A : 树型结构
B : 迟置信号后移
C : 资源共享
D : 流水线

个人选择 : ABD

10、 下面哪些属于动态验证范畴()
A : 形式验证
B : modelsim仿真
C: STA
D : 后仿

个人选择: BD
形式验证是一种静态的验证手段,根据电路结构静态地判断两个设计在功能上是否等价,常用来判断一个设计在修改前和修改后的功能是否一致。它运行时无需测试向量,但必须有一个参照设计和一个待验证的设计。

后仿:时序仿真加入布局布线的连线延迟,属于动态时序分析。

Modelsim仿真中既可以功能仿真(静态),也可以时序仿真(动态),时序仿真时,利用网表文件(.VO)和延时文件.sdo。
11、一批IC样品在测试中发现有setup或者hold时序问题。现取ABCD四颗样品进行测试。A降温后停止工作,则很可能是(1)问题;B升温后停止工作停止工作,则很可能是(2)问题;C降压后停止工作,则很可能是(3)问题;D升压后停止工作,则很可能是(4)问题。
(1)steup(40ns以下工艺)/hold(40ns以上工艺)
(2)hold(40ns以下工艺)/setup(40ns以上工艺)
(3)setup
(4)hold

温度和电压对应到管子行为上就是对于单个管子电流的影响。升温会使载流子速率降低,但是相应的也会使vth降低。电压的关系可以确定,setup可以用提高电压来满足,所以C降压后停止工作可能是setup问题,D升压后停止工作可能是hold问题。

12、OOP的三大特征是:继承、动态、封装;

13、已知R1=R2=R3=R4=R5=R6=R,下图从电源两端向右看去的等效电阻为(2R)

在这里插入图片描述
14、 用2048*12的ROM芯片,最多能实现(11)个输入,(12)个输出的组合逻辑函数。

15、以下Verilog代码的out[7:0]的逻辑可以用一条assign语句重写为()

wire [7:0] in,a,b;
reg [7:0] out;
genvar i;
generate
	for(i=0;i<8;i++) begin : gen_block
		always @(*) begin
			if(in[i])
				out[i] = a[i] ^ b[i];
			else begin
				if(i==0) 
					out[i]=1'b0;
				else 
					out[i] = in[i-1];
			end
		end
	end
endgenerate

assign out = in & (a ^ b) | ~in & {in[6:0],1’b0};
16、某个SRAM一共12根地址线A11~A0,32根数据线D31 ~ D0,如果要实现2^20bytes的memory,需要(64)块这样的SRAM?

2^20 * 8 / (2 ^12 * 32)

17、NAND和NOR Flash的主要区别是:(NAND Flash)中通常存在坏块、(NAND Flash)容量可以做到很大、(NAND Flash)写入速度比较快、(NOR Flash)读出速度比较快。

18、一个bits的输入A,A!=4‘b0,A中从MSB开始出现的第一个1的位置标示为B。
eg:A=4‘b0111, B = 2’b10(从MSB开始,第一个1出现在A的bit2)

答案:A[3] | A[2],A[3]|(!A[2]&A[1])
解析: A[3]=1时,B=2’11,B[1]=1,B[0]=1;
A[3]=0,A[2]=1时,B=2’10,B[1]=1,B[0]=0;
A[3]=0,A[2]=0,A[1]=1时,B=2’01,B[1]=0,B[0]=1;
A[3]=0,A[2]=0,A[1]=0,A[0]=1时,B=2’00,B[1]=0,B[0]=0;

19、在这里插入图片描述
这是3级JK触发器,转为D触发器的个还是写出Q0、Q1、Q2的表达式
结果是五(原因不会)

20、
在这里插入图片描述4*4矩阵键盘有四根行线和4跟列线,行选通和列选通可以确定键盘上的一个位置,行线上接了一个10K的上拉电阻接VCC,这使得键盘在没有按下时候,四根行线始终是高电平。

列线是处理器输入给矩阵键盘,空闲状态保持0,也就是行空闲时输出给处理器为4个1,列空闲时,由处理器输入给4个0.
当按下第一行第一个按键时,对应的那一行导通输出为0,即row_data=0111,此时由处理器逐渐输入列扫描信号由0111----1110,当所按下的按键对应的那一列的按键,矩阵键盘的行才会导通输出为0,否则会回到1111。
在这里插入图片描述
在这里插入图片描述
行列都是低有效

module key_scan(
	input clk,
	input rst_n,
	input [3:0] row_data,
	output key_flag,
	output reg [3:0] key_value,
	output reg [3:0] col_data
);


parameter SCAN_IDLE = 8'b0000_0001;
parameter SCAN_JITTER1 = 8'b0000_0010;
parameter SCAN_COL1 = 8'b0000_0100;
parameter SCAN_COL2 = 8'b0000_1000;
parameter SCAN_COL3 = 8'b0001_0000;
parameter SCAN_COL4 = 8'b0010_0000;
parameter SCAN_READ = 8'b0100_0000;
parameter SCAN_JITTER2 = 8'b1000_0000;


parameter DELAY_TRAN =2;
parameter DELAY_20MS = 1000_000;


reg [20:0] dealy_cnt;
reg delay_done;
reg [7:0] c_state,n_state;
reg [20:0] tran_snt;
reg tran_flag;

reg [3:0] row_data_r;
reg [3:0] col_data_r;

//----------------------------------------------
//delay 20ms
always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		delay_cnt <= 'd0;
	end
	else if(delay_cnt==DELAY_20MS) begin
		delay_cnt <= 'd0;
	end
	else if(n_state==SCAN_JITTER1 | n_state==SCAN_JITTER2) begin
		delay_cnt <= delay_cnt + 1'b1;
	end
	else begin
		delay_cnt <= 'd0;
	end
end

assign delay_done = (delay_cnt==DELAY_20MS-1'b1) ? 1'b1 : 1'b0;

//---------------------------------------------------------------------------
//delay 2 clk
always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		tran_cnt <= 'd0;
	end
	else if(tran_cnt==DELAY_TRAN) begin
		tran_cnt <= 'd0;
	end
	else begin
		tran_cnt <= tran_cnt + 1'b1;
	end
end

assign tran_flag = (tran_cnt==DELAY_TRAN) ? 1'b1 : 1'b0;
//---------------------------------------------------------------------------

//FSM step1
always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		c_state <= SCAN_IDLE;
	end
	else if(tran_flag) begin
		c_state <= n_state;
	end
	else begin
		c_state <= c_state;
	end
end

//FSM step2
always @ (*) begin
	case(c_state)
		SCAN_IDLE : begin
						if(row_data!=4'b1111) begin
							n_state = SCAN_JITTER1;
						end
						else begin
							n_state = SCAN_IDLE;
						end
					end
		SCAN_JITTER1 : begin
						if(row_data != 4'b1111 && delay_done) begin
							n_state = SCAN_COL1;
						end
						else begin
							n_state = SCAN_JITTER1;
						end
					end
		SCAN_COL1 : begin
						if(row_data != 4'b1111) begin   //如果row_data是全1,说明不是列扫描没有对应到该行
							n_state = SCAN_READ;
						end
						else begin
							n_state = SCAN_COL2;
						end
					end
		SCAN_COL2 : begin
						if(row_data != 4'b1111) begin   //如果row_data是全1,说明不是列扫描没有对应到该行
							n_state = SCAN_READ;
						end
						else begin
							n_state = SCAN_COL3;
						end
					end
		SCAN_COL3 : begin
						if(row_data != 4'b1111) begin   //如果row_data是全1,说明不是列扫描没有对应到该行
							n_state = SCAN_READ;
						end
						else begin
							n_state = SCAN_COL4;
						end
					end
		SCAN_COL4 : begin
						if(row_data != 4'b1111) begin   //如果row_data是全1,说明不是列扫描没有对应到该行
							n_state = SCAN_READ;
						end
						else begin
							n_state = SCAN_IDLE;
						end
					end
		SCAN_READ : begin
						if(row_data!=4'b1111) begin
							n_state = SCAN_JITTER2;
						end
						else begin
							n_state = SCAN_IDLE;
						end
					end
		SCAN_JITTER2 : begin
						if(row_data==4'b1111 && delay_done) begin
							n_state = SCAN_IDLE;
						end
						else begin
							n_state = SCAN_JITTLER2; 
						end
					end
		default : n_state = SCAN_IDLE;
	endcase
end

//--FSM step3
always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		col_data <= 4'b0000;
		row_data_r <= 4'b0000;
		col_data_r <= 4'b0000;
	end
	else if(tran_flag) begin
		case(n_state) 
			SCAN_COL1 : col_data = 4'b0111;
			SCAN_COL2 : col_data = 4'b1011;
			SCAN_COL3 : col_data = 4'b1101;
			SCAN_COL4 : col_data = 4'b1110;
			SCAN_READ : begin
				col_data <= col_data;
				row_data_r <= row_data;
				col_data_r <= col_data;
			end
			default: col_data <= 4'b0000;
        endcase
     end
    else begin
			col_data <= col_data;
			row_data_r <= row_data_r;
			col_data_r <= col_data_r;
	end
end
//这个状态表明是扫开消完抖动的那一瞬间
assign key_flag = (n_state == SCAN_IDLE && c_state == SCAN_JITTER2 && tran_flag)? 1'b1 : 1'b0;

//decode key_value
always  @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        key_value <= 'd0; 
    end
    else if(key_flag == 1'b1)begin
        case({row_data_r, col_data_r})
        8'b0111_0111: key_value <= 4'h1;  
        8'b0111_1011: key_value <= 4'h2;
        8'b0111_1101: key_value <= 4'h3;
        8'b0111_1110: key_value <= 4'ha;
        8'b1011_0111: key_value <= 4'h4;
        8'b1011_1011: key_value <= 4'h5;
        8'b1011_1101: key_value <= 4'h6;
        8'b1011_1110: key_value <= 4'hb;
        8'b1101_0111: key_value <= 4'h7;
        8'b1101_1011: key_value <= 4'h8;
        8'b1101_1101: key_value <= 4'h9;
        8'b1101_1110: key_value <= 4'hc;
        8'b1110_0111: key_value <= 4'hf;
        8'b1110_1011: key_value <= 4'h0;
        8'b1110_1101: key_value <= 4'he;
        8'b1110_1110: key_value <= 4'hd;
        default     : key_value <= key_value;
        endcase
    end
    else 
        key_value <= key_value;
end


endmodule

21、

在这里插入图片描述LSFR(线性反馈移位寄存器),LSFR的一般结构如下:
在这里插入图片描述
这个 多项式是一个本原多项式,下面m=3来做个例子具体的电路图如下所示:
在这里插入图片描述
假设开始的时候(D2,D1,D0)=(0,0,1),那么每过一个时钟周期会进行跳变一次,具体跳变如下:
在这里插入图片描述
无论进入除了0的状态,都可以循环着回来,相当于3bit的伪随机数。上面的电路可以看成是一个除法电路。现在假设R(x)是寄存器中剩余的数据,M(x)是输入的码字多项式。数学表达式可以表示成:
在这里插入图片描述在这里插入图片描述
发现7次方的运算和0次的时候的余数是一样的,上面的电路中多项式的除法也是可以循环起来的,可以验证的是
在这里插入图片描述
改成
在这里插入图片描述
CRC的计算也可以通过一个除法电路来实现。
假设码子多项式为:
在这里插入图片描述
生成多项式为:
在这里插入图片描述
那么CRC的码字是
在这里插入图片描述
用LFSR(线性反馈移位寄存器)实现。首先对M(x)乘以一个x^r,然后去除G(x),在电路上的表示就是:
在这里插入图片描述
所以在输入码字以后还需要多输入r拍的0,这样才能使最后的CRC码字数据,同理这个电路也可以进行CRC校验,把生成的数据全部都依次输入
CRC(cyclic redundancy check,循环冗余校验)是数据传输中常用的一种差错控制编码方式,针对要发送的数据帧,使用一些特定的多项式可以计算出CRC校验结果,CRC校验结果和原始数据一起传输到接收端。

基于多项式x^8 + x ^2 + x + 1的CRC算法,步骤如下:
(1)计算CRC之前,CRC寄存器初始化为一个已知值(初始值),接收端的CRC校验电路的初始值要使用和发送端相同的初始值。
(2)当最后一个数据bit到达时,CRC内部存储的就是最后的校验结果
(3)在最后一个数据bit发出后,储存在寄存器中的CRC结果逐比特输出,直至最后一个bit,校验结果紧随在用户数据后面输出。
在这里插入图片描述 CRC检验原理实际上就是在一个p位二进制数据序列之后附加一个r位二进制检验码(序列),从而构成一个总长为n=p+r位的二进制序列;附加在数据序列之后的这个检验码与数据序列的内容之间存在着某种特定的关系。如果因干扰等原因使数据序列中的某一位或某些位发生错误,这种特定关系就会被破坏。因此,通过检查这一关系,就可以实现对数据正确性的检验。

生成多项式:当进行CRC检验时,发送方与接收方事先约定一个除数,即生成多项式,一般记完G(x)。生成多项式的最高位和最低位必须是1,常用crc码生成多项式有:
CRC8=X8+X5+X4+1

CRC-CCITT=X16+X12+X5+1

CRC16=X16+X15+X5+1

CRC12=X12+X11+X3+X2+1

CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+1

每个生成多项式都可以与一个代码相对应,CRC8对应代码:100110001

该信息字段为k位,校验字段为R位,则码字长度为N(N=k+R),设双方事先约定一个R次多项式g(x),则CRC码:
V(x)=A(x)g(x)=x^Rm(x)+r(x)
其中:m(x)为k次信息多项式,r(x)为R-1次校验多项式
这里r(x)对应的代码即为冗余码,加在原信息段后即形成crc码。

r(x)的计算方法为:在K位信息字段的后面添加R个0,再除以g(x)对应的代码序列,得到的余数即为r(x)对应的代码(应为R-1位;若不足,而在高位补0)。

eg:
设需要发送的信息码为:M=1010_0011_01,产生的多项式对应的代码为p=110101,R=5,在M后面加5个0.然后对P做模2除法运算,余数r(x)对应的代码为:01110,实际要发送的数据为:101000110101110
在这里插入图片描述多项式模2运行:实际上是按位异或(Exclusive OR)运算,即相同为0,相异为1,也就是不考虑进位、借位的二进制加减运算

在这里插入图片描述在这里插入图片描述D15…D0中的数据即为所要求的余数,即CRC校验位。

如果用时序电路串行实现,则8bit数据要移位8次,就需要8个clk,效率低下,为了能在一个时钟周期输出结果,必须采用组合电路,以空间换时间,使用for循环了8次


module crc_gen(
	input clk ,
	input rst_n,
	input [7:0] data_in,
	input d_valid,
	output reg [15:0] crc
);


integer i;
reg feedback;
reg [15:0] crc_temp;

//sequential process
always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin     //触发器中的初始值非常重要
		crc <= 16'b0;
	end
	else if(!d_valid) begin
		crc <= 16'b0;
	end
	else begin
		crc <= crc_temp;
	end
end

always @ (data_in or crc) begin
	crc_temp = crc;
	for(i=7;i>=0;i=i-1)
	begin
		feedbak = crc_temp[15] ^ data_in[i];
		crc_temp[15] = crc_temp[14];
		crc_temp[14] = crc_temp[13];
		crc_temp[13] = crc_temp[12];
		crc_temp[12] = crc_temp[11] ^ feedback;
		crc_temp[11] = crc_temp[10];
		crc_temp[10] = crc_temp[9];
		crc_temp[9] = crc_temp[8];
		crc_temp[8] = crc_temp[7];
		crc_temp[7] = crc_temp[6];
		crc_temp[6] = crc_temp[5];
		crc_temp[5] = crc_temp[4] ^ feedback;
		crc_temp[4] = crc_temp[3];
		crc_temp[3] = crc_temp[2];
		crc_temp[2] = crc_temp[1];
		crc_temp[1] = crc_temp[0];
		crc_temp[0] = feedback;
	end
end
endmodule


//判断报文信息首位是否为0,若为0,则将报文信息左移一位进行计数,若为1,则将报文信息与多项式生成的数据进行逐位异或
//运算。将得到信息保存在寄存器中,并且开始计数,再将报文信息左移一位,将得到的结果替换报文信息高17位,继续与已知
//多项式进行异或运算。
module crc32(
	input clk,
	input rst_n,
	input valid,
	input [31:0] din,
	output [15:0] mod,
	output valid_mod
);

reg [47:0] D;
wire [16:0] Q;
reg [5:0] count;

always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		D <= 48'b0;
	end
	else if(valid) begin
		D <= {din,16'b0};
	end
	else begin
		D <= {Q,D[30:0]} <<1;
	end
end
assign Q = (D[47]) ? (D[47:31]^17'b1000_1000_0001_0000_1) : D[47:31];

assign valid_mod = (count==6'd1);
assign mod = Q[15:0];

always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		count <= 6'd0;
	end
	else if(valid) begin
		count <= 6'd30;
	end
	else if(count!=6'd0) begin
		count <= count - 1'b1;
	end
end




endmodule

关于这个题目就把上面的代码改成是,串行输入,以及把得到的CRC在进行并串转换。

猜你喜欢

转载自blog.csdn.net/weixin_43727437/article/details/106660767