笔试题总结

1.建立时间保持时间概念

建立时间(setup)是指在触发器的时钟信号上升沿到来以前,数据稳定不变的时间,如果建立时间不够,数据将不能在这个时钟上升沿被打入触器。

保持时间(hold)是指在触发器的时钟信号上升沿到来以后,数据稳定不变的时间,如果保持时间不够,数据同样不能被打入触发器。

每个时钟上升沿之前的是建立时间,上升沿之后的是保持时间,如果建立和保持时间都取极限最大值,把周期填满,它们相加肯定等于周期T。即Tsu(max)+Thold(max)=T。

 2.FIFO
module syn_fifo#(
	parameter 		WIDTH		=	16,
	parameter 		DEPTH		=	1024,
	parameter 		ADDR_WIDTH	=	clogb2(DEPTH),
	parameter 		PROG_EMPTY	=	100,
	parameter 		PROG_FULL	=	800
)(
	input 			sys_clk,
	input 			sys_rst,
	input			[WIDTH-1:0]din,
	input 			wr_en,
	input 			rd_en,
	output reg		[WIDTH-1:0]dout,
	output reg 		full,
	output reg 		empty,
	output reg 		prog_full,
	output reg 		prog_empty,
	output reg		[ADDR_WIDTH-1:0]fifo_cnt
);
//==========================================================\
//========== Define Parameter and Internal signals =========
//==========================================================/
reg		[WIDTH-1:0]			ram[DEPTH-1:0];
reg		[ADDR_WIDTH-1:0]	wr_addr;
reg		[ADDR_WIDTH-1:0]	rd_addr;
//==========================================================\
//===================== Main  Code =========================
//==========================================================/
function integer clogb2;
	input[31:0]value;
	begin
		value=value-1;
		for(clogb2=0;value>0;clogb2=clogb2+1)
			value=value>>1;
	end
endfunction
//read
always@(posedge sys_clk or posedge sys_rst)begin 
	if(sys_rst)
		rd_addr		<=		{ADDR_WIDTH{1'b0}};
	else if(rd_en && !empty)begin
		rd_addr		<=		rd_addr+1'd1;
		dout		<=		ram[rd_addr];
		end
	else begin
		rd_addr		<=		rd_addr; 
		dout		<=		dout;
		end
end
//write
always@(posedge sys_clk or posedge sys_rst)begin 
	if(sys_rst)
		wr_addr		<=		{ADDR_WIDTH{1'b0}};
	else if(wr_en && !full) begin
		wr_addr		<=		wr_addr+1'd1;
		ram[wr_addr]<=		din;
		end
	else
		wr_addr		<=		wr_addr;
end					
//fifo_cnt
always@(posedge sys_clk or posedge sys_rst)begin 
	if(sys_rst)
		fifo_cnt	<=		{ADDR_WIDTH{1'b0}};
	else if(wr_en && !full && !rd_en)
		fifo_cnt	<=		fifo_cnt + 1'd1;
	else if(rd_en && !empty && !wr_en)
		fifo_cnt	<=		fifo_cnt - 1'd1;	
	else 
		fifo_cnt	<=		fifo_cnt;
end
//empty 
always@(posedge sys_clk or posedge sys_rst)begin
	if(sys_rst)
		empty	<=	1'b1;//reset:1
	else
		empty	<=	(!wr_en && (fifo_cnt[ADDR_WIDTH-1:1] == 'b0))&&((fifo_cnt[0] == 1'b0) || rd_en);
end
//full
always@(posedge sys_clk or posedge sys_rst)begin
	if(sys_rst)
		full	<=	1'b1;//reset:1
	else
		full	<=	(!rd_en	&&	(fifo_cnt[ADDR_WIDTH-1:1]=={(ADDR_WIDTH-1){1'b1}})) && ((fifo_cnt[0] == 1'b1) || wr_en);
end
//prog_full
always@(posedge sys_clk or posedge sys_rst)begin
	if(sys_rst)	
		prog_full<=	1'b1;//reset:1
	else if(fifo_cnt > PROG_FULL)
		prog_full<=	1'b1;
	else
		prog_full<=	1'b0;
end
//prog_empty
always@(posedge sys_clk or posedge sys_rst)begin 
	if(sys_rst)
		prog_empty<=1'b1;//reset:1
	else if(fifo_cnt < PROG_EMPTY)
		prog_empty<=1'b1;
	else
		prog_empty<=1'b0;
end
endmodule


异步fifo,读写时钟不一致;同步fifo,读写时钟一致

写入频率和读出频率不一致时要计算fifo数据深度

题目:100个写时钟周期可以写入80个数据,10个读时钟可以读出8个数据,计算FIFO深度
解析: 写时钟频率 w_clk,
读时钟频率 r_clk,
写时钟周期里,每B个时钟周期会有A个数据写入FIFO
读时钟周期里,每Y个时钟周期会有X个数据读出FIFO
则,FIFO的最小深度是?
计算公式如下:
fifo_depth = burst_length - burst_length * X/Y * r_clk/w_clk

所以带入:
fifo_depth = 160-160X(80%)=160-128= 32


3.跨时钟域

单比特信号:

慢时钟域到快时钟域:因为快时钟一定能采样到慢时钟域内的信号,我们用两级寄存器进行同步的目的在于消除亚稳态问题

快时钟域到慢时钟域:在快时钟域内先进行脉冲展宽,展宽到慢时钟内能采样到为止;展宽之后的信号在慢时钟域clkb下用两级寄存器同步下就好了

多比特信号的跨时钟域传输:从快到慢,还是从慢到快,都可以用异步FIFO

                                                可以采用保持寄存器加握手信号的方法(多数据,控制,地址)

4.时序约束步骤

时钟约束 —> 输入/输出接口约束 —> 时钟分组和跨时钟约束 —> 时序例外约束。

5.奇偶分频

偶分频:四分频为例cnt计数到1拉高,记数到3拉低
奇分频 :五分频为例上升沿下降沿各一次,然后两个结果或运算

always@(posedge sys_clk or negedge sys_rst)

always@(negedge sys_clk or negedge sys_rst)



6.数字时钟时分秒

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值