本文转载自:OpenFPGA
1、用状态机实现10010码的探测,如x=1001001000 z=0000100100(输出)
module check(rst_i,clk_i,data_i,data_o);
input rst_i,clk_i;
input data_i;
output data_o;
reg[3:0] current_state,next_state;
parameter[3:0]
idle="0000",
state1="0001",
state2="0010",
state3="0100",
state4="1000";
always@(posedge clk_i or negedge rst_i)
if (!rst_i)
current_state<=idle;< span="">
else
current_state<=next_state;
always@(current_state,data_i)
case(current_state)
idle : if (data_i==1)next_state=state1;
else next_state=idle;
state1: if (data_i==0)next_state=state2;
else next_state=idle;
state2: if (data_i==0)next_state=state3;
else next_state=idle;
state3: if (data_i==1)next_state=state4;
else next_state=idle;
state4: if (data_i==0)next_state=idle;
else next_state=idle;
endcase
assign data_o= (current_state==state4);
endmodule
VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity check is
port(
rst_i :in std_logic;
clk_i :in std_logic;
data_i:in std_logic;
data_o:out std_logic);
end entity;
--}} End of automatically maintained section
architecture behave of check is
type state is (state_a,state_b,state_c,state_d,state_e);
signal current_state:state;
signal next_state:state;
begin
--type state is (state_a,state_b,state_c,state_d);
process(rst_i,clk_i)
begin
if rst_i='1' then
data_o<='0';< span="">
current_state<=state_a;< span="">
elsif rising_edge(clk_i) then
current_state<=next_state;< span="">
end if;
end process;
process(current_state,data_i)
begin
case current_state is
when state_a => if data_i='1' then
next_state<=state_b;< span="">
else
next_state<=state_a;< span="">
end if;
when state_b => if data_i='0' then
next_state<=state_c;< span="">
else
next_state<=state_a;< span="">
end if;
when state_c => if data_i='0' then
next_state<=state_d;< span="">
else
next_state<=state_a;< span="">
end if;
when state_d => if data_i='1' then
next_state<=state_e;< span="">
else
next_state<=state_a;< span="">
end if;
when state_e => if data_i='0' then
next_state<=state_a;
else
next_state<=state_a;< span="">
end if;
when others => null;
end case;
end;
data_o <='1' when current_state = state_e else '0';
end;
3、 用D触发器实现2倍分频的逻辑电路?
module divide2( clk , clk_o, reset);
input clk , reset;
output clk_o;
wire in;
reg out ;
always @ ( posedge clk or posedge reset)
if ( reset)
out <= 0;
else
out <= in;
assign in = ~out;
assign clk_o = out;
endmodule
4、 试用VHDL或VERILOG、ABLE描述8位D触发器逻辑。
module dff8(clk , reset, d, q);
input clk;
input reset;
input [7:0] d;
output [7:0] q;
reg [7:0] q;
always @ (posedge clk or posedge reset)
if(reset)
q <= 0;
else
q <= d;
endmodule
5、 给了reg的setup,hold时间,求中间组合逻辑的delay范围。
Delay < period - setup - hold
6、 写异步D触发器的verilog module
module dff8(clk , reset, d, q);
input clk;
input reset;
input d;
output q;
reg q;
always @ (posedge clk or posedge reset)
if(reset)
q <= 0;
else
q <= d;
endmodule
8、
R1反馈回到自身需要的时间为7(=1+ 5*1+T_setup)
R2反馈加到自身需要的时间为6(=1+2*1+2+T_setup)
显然,最小周期不能小于7,即T>=7。(否则,R1不能正确采样到其反馈值)
所以答案分别是:
1)1+5*1+2+1=9
2)1+5*1+2+1- T_skew = 8
3)1+5*1+2+1-T_skew = 5,但因为T>=7,所以Tmin=7
4)记T_skew = t2 - t1,
则正偏时,T_skew必须小于R1到R2的最小延时(不包括Tsetup),即T_skew<6(=1+3*1+2),以保证,r2采样到正确的值
负偏差时,T- (T_skew的绝对值)必须大于或等于R1到R2的最大延时9,即(T_skew的绝对值)<=t-9
综合一下,就是(9-T) ≤ T_skew < 6
系统时钟周期 Tclk>=Tco+T logic delay max+T2setup-Tskew
正偏时,不但要考虑T>=Tco+Tlogic+Tsu-Tskew(且只需在T<9的情况下考虑),还要考虑(tco+tlogic)min>Tskew+Thold(但这里Thold没给出就当作是零),否则会有数据冲突,使得R2不能正确采样前一周期从R1传来的值,所以就是Tskew<(tco+tlogic)min=6
所以正偏时,9-T≤ Tskew<6
负偏时,根据T>=Tco+Tlogic+Tsu-Tskew,就可以得到9-T≤ Tskew。
而不等式(Tco+Tlogic)min >Tskew+Thold,因Thold已经当作零,Tskew为负值,恒成立。
所以负偏时9-T≤ Tskew<=0
将两种请况综合就是9-T≤ Tskew<6< span="">
11、 用一个二选一mux和一个inv实现异或。(飞利浦-大唐笔试)
input a,b;
output c;
assign c=a?(~b):(b);
14、 写异步D触发器的verilog module。(扬智电子笔试)
module dff8(clk , reset, d, q);input clk;input reset;input [7:0] d;output [7:0] q;reg [7:0] q;always @ (posedge clk or posedge reset)if(reset)q <= 0;elseq <= d;endmodule
15、 用D触发器实现2倍分频的Verilog描述? (汉王笔试)
module divide2( clk , clk_o, reset); input clk , reset; output clk_o; wire in;reg out ; always @ ( posedge clk or posedge reset)if ( reset)out <= 0;elseout <= in;assign in = ~out;assign clk_o = out; endmodule
16、 饮料10分钱,硬币有5分、10分两种,投币一次或者两次,累计大于或者等于10分时,饮料弹出,有多余的硬币,也会弹出,由此可知,可以分为两个状态,一个是0分,一个是5分。累计的币值等于10分,则弹出饮料,找零0分;累计的币值为15分,则弹出饮料,找零5分。
状态转移图:
代码设计:
FIFO 是先入先出存储器的缩写,FIFO 控制器在数字系统中被大量使用,可以作为数据缓存
使用。时钟同步的FIFO 控制器接口如下图所示,主要接口信号定义如下:
RST_N:异步复位信号,当RST_N 为低电平时,FULL 输出‘0’,EMPTY 信号输出‘1’
电平,FIFO 指针指向0,FIFO 被清空;
CLK:时钟信号,输出信号与CLK 信号同步;
DATAIN:数据输入信号,8 位总线;
RD:读有效信号,高电平有效,当RD 位高时,在时钟信号CLK 的上升沿,DATAOUT 输
出一个8 位的有效数据;
WR:写有效信号,当WR 为高电平时,在CLK 的上升沿,从DATAIN 信号向存储器写入
一个8 位的有效数据;
DATAOUT:数据输出信号,8 位总线,在CLK 的上升沿,当RD 为高电平时,从FIFO 中
输出一个8 位的数据;
FULL:存储器写满标志信号,高电平时表示存储器中的数据已经写满;
EMPTY:存储器读空标志信号,高电平时表示存储器中的数据已经被读空了。
要求:用Verilog 写一个8x16 的FIFO,完成先入先出的功能,并且在FIFO读空时输出EMPTY
有效信号,读指针RP 不再移动;FIFO 写满时输出FULL 有效信号,并且即使WR 有效也
不再向存储单元中写入数据(写指针WP 不再移动)。
存储单元使用一个二维数组来建模。注意存储单元的地址在读或者写到最高地址时要能回到最低值。
module fifo_mem(data,clk,rstN,wrN,rdN,empty,full);inout [7:0] data;input clk,rstN,wrN,rdN;output empty,full;reg [4:0] _cntr,rd_cntr;wire [3:0] add;ram16X8 ram(.data(data),.addr(addr),.wrN(wrN),.oe(wrN));always @(posedge clk or negedge rstN)if(!rstN) wr_cntr<=0;else if (!wrN) wr_cntr<=wr_cntr+1;always @ (posedge clk or negedge rstN) if(!rstN) rd_cntr<=0; else if(!rdN) rd_cntr<=rd_cntr+1;assign addr=wrN?rd_cntr [3:0]: wr_cntr [3:0];assign empty=(wr_cntr [3:0] == rd_cntr [3:0])&&!(wr_cntr[4]^rd_cntr[4]);assign full=(wr_cntr [3:0] ==rd_cntr [3:0])&&(wr_cntr[4]^rd_cntr[4]);endmodule
18、 用你熟悉的设计方式设计一个可预置初值的7进制循环计数器,15进制的呢?
module counter7(clk,rst,load,data,cout);
input clk,rst,load;
input [2:0] data;
output reg [2:0] cout;
always@(posedge clk)
begin
if(!rst)
cout<=3’d0;
else if(load)
cout<=data;
else if(cout>=3’d6)
cout<=3’d0;
else
cout<=cout+3’d1;
end
endmodule