1.寄存器与锁存器
flip-flop:触发器,是时钟边沿触发,可存储1 bit data,是register的基本组成单位,结构图如下:
register:寄存器,a hardware register stores bits of information in such a way that systems can write to or read out all the bits simultaneously.就是时钟边沿触发的存储结构,是由多个flip-flop组成,可以构成register file, SRAM等,结构如下:
时序逻辑结构
latch:锁存器,是由电平触发,结构图如下:
组合逻辑结构
那么其在FPGA上的实现方法:
但是为什么这样的方法就可以实现FPGA的浮点输的转化呢?表示比较疑惑
7.状态机设计:实现序列检测:
根据要检测的序列的长度决定状态的个数,然后设计好状态转移图:根据三段式的设计方案,即可以实现状态机的编写:
三段式序列检测"10010" module seqdet(din,clk,rst,dout); input din; //输入 input clk; input rst; output dout; //输出 reg dout; reg [4:0] CS; //现态寄存器 reg [4:0] NS; //次态寄存器 parameter [4:0] IDLE = 5'b00000, //独热码 A = 5'b00001, B = 5'b00010, C = 5'b00100, D = 5'b01000, E = 5'b10000; always @ (posedge clk or negedge rst) if (!rst) CS <= IDLE; else CS <= NS ; always @ ( CS or din ) begin NS = 5'bx; case (CS) IDLE : NS = din ? A : IDLE; A : NS = din ? A : B; B : NS = din ? A : C; C : NS = din ? D : IDLE; D : NS = din ? A : E; E : NS = din ? A : C; default: NS = IDLE; endcase end always @ ( posedge clk or negedge rst) if (!rst) dout <= 1'b0; else begin dout <= 1'b0; if (NS == E) dout <= 1'b1; end endmodule
状态机之并行数据串行化:
//并行数据串行化 module b2c(din8,clk,slr,din); input clk,clr; input [7:0]din8; output din; reg [2:0]cs,ns; reg dout; always@(posedge clk or posedge clr) begin if(clr) cs<=0; else cs<=ns; end always@(clk or din8 or dout) begin case(cs) 3'b0: begin din<din8[7]; ns<=3'b1; end 3'b1: begin din<din8[6]; ns<=3'b2; end 3'b2: begin din<din8[5]; ns<=3'b3; end 3'b3: begin din<din8[4]; ns<=3'b4; end 3'b4: begin din<din8[3]; ns<=3'b5; end 3'b5: begin din<din8[2]; ns<=3'b6; end 3'b6: begin din<din8[1]; ns<=3'b7; end 3'b7: begin din<din8[0]; ns<=3'b0; end default: begin din<=1'b0; ns<=0; end endcase end endmodule
8.FIFO深度计算,原来这也是一个神奇的问题啊,首先需要了解其应用的场景,FIFO主要用于数据的缓存,在写快但是读慢的情形下,主要考虑到读写时钟的不一致性问题,主要的计算公式:depth of fifo=FIFO被填满的时间*(w_clk - r_clk)大于数据包的传送时间=数据量 / 写入速度。
以下是网上整理到的资料:
首先,一定要理解清楚FIFO的应用场景,这个会直接关系到FIFO深度的计算,如果是面试官抛出的问题,那么有不清楚的地方,就应该进行询问。如果是笔试或者工程中需要计算FIFO深度的话,那么就需要自己考虑清楚。
其次,异步FIFO,读写时钟不同频,那么FIFO主要用于数据缓存,我们选择的FIFO深度应该能够保证在最极端的情况下,仍然不会溢出。因此考虑的前提一般都是写时钟频率大于读时钟频率,但是若写操作是连续的数据流,那么再大的FIFO都无法保证数据不溢出。因此可以认为这种情况下写数据的传输是“突发Burst”的,即写操作并不连续,设计者需要根据满标志控制或者自己来控制写操作的起止。
宏观地,从整个时间域上看,"写数据=读数据",这个条件必须要满足,如果这个大条件不满足的话,用FIFO是没有效果的。但是在发送方"突发"发送数据的时间T内,是很有可能写数据>读数据的,因此FIFO的深度要能够保证,在这段时间T内,如果接收方未能将发送方发送的数据接收完毕的话,剩下的数据都是可以存储在FIFO内部而且不会溢出的,那么在发送方停止发送数据的"空闲时隙"内,接收方可以从容地接收剩下来的数据。
写时钟周期w_clk,
读时钟周期r_clk,
写时钟周期里,每B个时钟周期会有A个数据写入FIFO
读时钟周期里,每Y个时钟周期会有X个数据读出FIFO
则,FIFO的最小深度是?
首先,这道题不一定有解
有解的必要条件是在一定时间内(足够长),写入的数据数量一定要等于读出的数据数量
因此有:A/B * w_clk = X/Y * r_clk
其次,算出写数据的最大burst_length。考虑最坏情况
比如,如果条件给出,每100个写时钟,写入80个数据,那么在背靠背的情况下,burst_length = 2*80=160
最后,fifo_depth = burst_length - burst_length * X/Y * r_clk/w_clk
BTW:通常,为了安全起见,都会多留一些depth的余度
个人觉得,公式应该是这样:
A/(B * w_clk) = X/(Y * r_clk)
fifo_depth = burst_length - burst_length * X/Y * w_clk /r_clk
举例说明:
如果100个写时钟周期可以写入80个数据,10个读时钟可以读出8个数据
其中w_ck=5ns,r_ck=10ns
如果按照之前的公式,得出的深度为:fifo_depth = burst_length - burst_length * X/Y * r_ck/w_clk=160-160*8/10*2=-94,显然是不对的
实际上,考虑背靠背(20个clk不发数据+80clk发数据+80clk发数据+20个clk不发数据的200个clk)
这样在中间160个写时钟周期连续写的情况下,只能读出160*5/(10*10)*8=64个数据,所以FIFO的深度应该为160-64=96
也就是fifo_depth = burst_length - burst_length * X/Y * w_clk /r_clk=160-160*8/10*5/10=96
9.同步异步电路分析
在同步电路设计中一般采用D触发器,异步电路设计中一般采用Latch。两者的最大的区别就在于,同步电路有统一的时钟,但是异步电路没有统一的时钟,
异步复位信号同步释放:其中的异步复位是指复位信号是异步有效的,即复位的发生与clk无关。后半句“同步释放”是指复位信号的撤除也与clk无关,但是复位信号是在下一个clk来到后起的作用(释放)。
10.各类存储器之间的区别(详见之前写的一篇博客的内容总结部分)。
11.对竞争冒险的理解,以及如何消除?
在组合逻辑中,由于门的输入信号通路中经过了不同的延时,导致到达该门的时间不一致叫竞争。产生毛刺叫冒险。如果布尔式中有相反的信号则可能产生竞争和冒险现象。解决方法:一是添加布尔式的消去项,二是在芯片外部加电容。
12分频器的设计(任意分频通用设计)
module square_generator#(parameter FREQ_WORD = 32'd85899) (LedCtlWordLocal,clk,rst_n,clk_outI,clk_outQ); input LedCtlWordLocal; input clk; //50MHz input rst_n;//clock reset output reg clk_outI,clk_outQ; //-------------------------------------- reg [31:0] count='b1; always@(posedge clk) begin count <= count + FREQ_WORD; end //-------------------------------------- always@(posedge clk or negedge rst_n) begin if(!rst_n) clk_outI <= 'b1; else begin if(count < 32'h7FFF_FFFF) clk_outI <= 'b1; else clk_outI <= LedCtlWordLocal; if((count>32'h3FFFFFFF)&&(count < 32'hbFFFFFFF)) clk_outQ <= 1'b1; else clk_outQ <= LedCtlWordLocal; end end endmodule