1、十进制46.25对应的二进制表达式为( D )。
A 101110.11
B 101101.01
C 101110.1
D 101110.01
解析:整数部分的结果为:
小数部分的结果为:
2、在时序电路的状态转换表中,若状态数N=3,则状态变量数最少为( C )
A 4
B 8
C 2
D 16
解析过程如下:
01module simple_fsm(
02input wire sys_clk , //系统时钟50Mhz
03input wire sys_rst_n , //全局复位
04input wire pi_money , //投币方式可以为:不投币(0)、投1元(1)
05
06output reg po_cola //po_cola为1时出可乐,po_cola为0时不出可乐
07);
08
09//只有三种状态,使用独热码
10parameter IDLE =3'b001;
11parameter ONE =3'b010;
12parameter TWO =3'b100;
13
14reg [2:0] state;
15
16//第一段状态机,描述当前状态state如何根据输入跳转到下一状态
17always@(posedge sys_clk ornegedge sys_rst_n)
18if(sys_rst_n ==1'b0)
19 state<= IDLE;
20elsecase(state)
21 IDLE : if(pi_money ==1'b1)//判断输入情况
22 state<= ONE;
23 else
24 state<= IDLE;
25
26 ONE :if(pi_money ==1'b1)
27 state<= TWO;
28 else
29 state<= ONE;
30
31 TWO : if(pi_money ==1'b1)
32 state<= IDLE;
33 else
34 state<= TWO;
35
36 default: state <= IDLE;
37 endcase
38
39//第二段状态机,描述当前状态state和输入pi_money如何影响po_cola输出
40always@(posedge sys_clk ornegedge sys_rst_n)
41if(sys_rst_n == 1'b0)
42 po_cola<=1'b0;
43else if((state == TWO)&&(pi_money ==1'b1))
44 po_cola<=1'b1;
45else
46 po_cola<=1'b0;
47
48endmodule
其功能是每次只能输入1元硬币,输入3元时出可乐
上面的例子中10-12行是状态编码,即有多少个状态数就需要有多少个状态编码,这里一共有3种;14行是状态变量,这里为什么状态变量的位宽是3呢?因为我们采用了独热码的编码方式,每个状态数只有1比特为1,其余比特都为0,所以3个状态就要用3位宽的变量,如果是4个状态那就要用4位宽的变量,也就是一共有几个状态数就需要几位宽的状态变量。而题目中说的是“最少“,那么除了我们用独热码的方式对状态进行编码,还有其他的方法吗?答案是当然。我们还可以采用二进制码或格雷码的方式对状态进行编码,上面的例子中如果我们用二进制码编码3个状态则为:2‘b00,2‘b01,2‘b10;而用格雷码编码3个状态则为:2‘b00,2‘b01,2‘b11,都只需要2位宽的状态变量即可,即便是有4个状态数,我们使用2位宽的
关于为什么使用的是独热码而不是二进制码或格雷码。因为独热码的每个状态只有1bit是不同的,所以在执行到43行state==TWO时,综合器会识别出这是一个比较器,因为只有1bit为1,所以综合器就会进行智能优化为state[2]==1‘b1,这就相当于把3bit的综合器优化为1bit的比较器,这就大大节省了逻辑资源,付出的代价就是状态变量的位宽需要的就比较多,在FPGA中组合逻辑资源相对较少,寄存器资源较多。
二进制编码的情况和独热码刚好相反,使用了少量的状态变量,使之在减少寄存器状态的同时无法进行比较器部分之间的优化,所以使用的寄存器资源较少,而使用的组合逻辑资源较多。
独热码编码的状态机可以在高速系统上运行,因为是多比特的比较器每个比特到达比较器的时间可能会因为布局布线的走线长短而导致路径延时的不同,这样在高速系统下就会导致采集到不稳定的状态,导致比较后的结果产生一个时钟的毛刺,使输出不稳定,而单比特的比较器不用考虑这个问题。
如果状态数非常多的话即使是FPGA也吃不消独热码对寄存器的消耗,所以当状态数特别多的时候可以使用格雷码对状态进行编码。格雷码虽然也是和二进制编码一样使用的寄存器资源少,组合逻辑资源多,但是其相邻状态转换时只有一个状态发生翻转,这样不仅能消除状态转换时由多条信号线的传输延迟所造成的毛刺,又可以降低功耗,所以要优于二进制编码的方式,相当于是独热码和二进制编码的折中。
3、使用2-1MUX设计INV,AND,OR,NAND,NOR。
MUX是能够根据需要将其中任意一路选出来的电路,又称为数据选择器。
(1)、设计INV
使用MXU设计INV,需要将S1端接“0”,将S0端接“1”。
(2)、设计AND
使用MXU设计AND,需要将S1端接A,将S0端接“0”。
(3)、设计OR
使用MXU设计OR,需要将S1端接“1”,将S0端接B。
NAND和NOR可以在AND和OR的基础上增加一个INV得到。
4、异步FIFO的深度计算
FIFO主要用于异步数据传输之间的数据缓冲。我们选择的FIFO深度应该能够保证在最极端的情况下,仍然不会溢出。因此考虑的最坏情况一般都是写时钟频率大于读时钟频率,但是若写操作是连续的数据流,FIFO都无法保证数据不溢出。可以认为写数据的传输是“突发burst”的,即写操作并不连续。
从整个时间域上看,“写数据=读数据”。但是在发送方"突发"发送数据的时间T内,是很有可能写数据>读数据的,因此FIFO的深度要能够保证,在这段时间T内,如果接收方未能将发送方发送的数据接收完毕的话,剩下的数据都是可以存储在FIFO内部而且不会溢出的。
**实例:**一个8bit宽的异步FIFO,输入时钟为100MHz,输出时钟为95MHz,设一个数据包为4Kbit,且两个数据包之间的发送间距足够大。问异步FIFO的深度至少为多少?
发送发一次Burst突发的数据量为4Kbit,即500byte,在两次Burst突发之间有足够的时间,因此我们只用考虑在发送方Burst发送数据的时间T内,如果接受方没法将数据全部接收,其余数据均可存在FIFO内且不溢出。首先发送方Burst发送数据的时间段为 T = 500/100MHz。而在T这段时间内,接收方能够接受的数据量为B_receive = T*95MHz = 500 * 95 / 100 byte = 475 byte,因此 B_remain = B_send - B_ receive = 500 -475 = 25 byte。那么FIFO的深度至少要大于等于25 byte才行。
5、如果只使用2选1mux完成异或逻辑,至少需要几个mux?
Y= A xor B=A!B+AB!= (A == 1’b0) ?B: B!= (A ==1’b0) ?B: ( (B==1’b0) ? 1’b1: 1’b0)
6、将二输入的与非门当非门使用时,另一端的接法应该是
Y= !A=!(1’b1 && A)
所以另一端接高电平
7、时序检查中对异步复位电路的时序分析叫做()和()?
恢复时间检查和移除时间检查。recovery time 和removal time检查
8、用Verilog实现一个可综合的50%占空比的三分频电路,并画出Timing图。
占空比为50%的三分频电路就需要同时使用时钟的上升沿和下降沿,然后将信号组合成时钟的三分频。但是,不能在同一个always语句内同时使用时钟的上升沿和下降沿。
方法(1):Clock3=Clock1|Clock2
module three_div1(
input clk ,
input rst_n,
output clk_out);
reg [1:0] count1,count2;
reg clk_out1,clk_out2;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
count1 <= 0;
clk_out1 <= 0 ;
end
else if(count1 == 1)begin
count1 <= count1 +1 ;
clk_out1 <= 1 ;
end
else if(count1 == 2)begin
count1 <= 0;
clk_out1 <= 0 ;
end
else begin
count1 <= count1 +1 ;
end
end
always@(negedge clk or negedge rst_n) begin
if(!rst_n) begin
count2 <= 0;
clk_out2 <= 0 ;
end
else if(count2 == 1)begin
count2 <= count2 +1 ;
clk_out2 <= 1 ;
end
else if(count2 == 2)begin
count2 <= 0;
clk_out2 <= 0 ;
end
else begin
count2 <= count2 +1 ;
end
end
assign clk_out = clk_out1 | clk_out2;
endmodule
方法(2):Clock3=Clock1 & Clock2
module three_div2(
input clk ,
input rst_n,
output clk_out);
reg [1:0] count1,count2;
reg clk_out1,clk_out2;
always@(posedge clk or negedge rst_n)begin
if(!rst_n) begin
count1 <= 0;
clk_out1 <= 0 ;
end
else if(count1 == 1)begin
count1 <= count1 +1 ;
clk_out1 <= 0 ;
end
else if(count1 == 2)begin
count1 <= 0;
clk_out1 <= 1 ;
end
else begin
count1 <= count1 +1 ;
end
end
always@(negedge clk or negedge rst_n)begin
if(!rst_n) begin
count2 <= 0;
clk_out2 <= 0 ;
end
else if(count2 == 1)begin
count2 <= count2 +1 ;
clk_out2 <= 0;
end
else if(count2 == 2)begin
count2 <= 0;
clk_out2 <= 1 ;
end
else begin
count2 <= count2 +1 ;
end
end
assign clk_out = clk_out1 & clk_out2;
endmodule