常见面试笔试题verilog程序库

常见面试笔试题verilog程序库
常见面试笔试题verilog程序库

常见面试笔试题-verilog程序库

————————————————————————————————作者:————————————————————————————————日期:

加减法

module addsub

( input [7:0] dataa,

input [7:0] datab,

input add_sub,//if thisis1, add; else subtract

input clk,

output reg [8:0] result );

always @ (posedge clk)

begin

if (add_sub) result<= dataa + datab;//or "assign {cout,sum}=dataa+datab;"

elseresult <=dataa- datab;

end

endmodule

四位的全加法器.

module add4(cout,sum,a,b,cin)

input[3:0]a,b; input cin;

output [3:0] sum; output cout;

assign?{cout,sum}=a+b+cin;

endmodule

补码不仅可以执行正值和负值转换,其实补码存在的意义,就是避免计算机去做减法的操作。

1101 -3 补

+ 1000 8

01015

假设-3 + 8,只要将-3 转为补码形式,亦即0011 => 1101,然后和8,亦即1000 相加

就会得到5,亦即0101。至于溢出的最高位可以无视掉。

乘法器

modulemult(outcome,a,b);

parameter SIZE=8;

input[SIZE:1] a,b;

outputreg[2*SIZE:1] outcome;

integer i;

always@(aor b)

begin outcome<=0;

for(i=0,i<=SIZE;i=i+1)

if(b[i]) outcome<=outcome+(a<<(i-1));

end

endmodule

另一种乘法器。在初始化之际,取乘数和被乘数的正负关系,然后取被乘数和乘数的正值。输出结果根据正负关系取得。

else if( Start_Sig)

case( i)

0: begin

isNeg<= Multiplicand[7]^ Multiplier[7];

Mcand <=Multiplicand[7] ?( ~Multiplicand + 1'b1 ) : Multiplicand;

Mer<= Multiplier[7] ? (~Multiplier + 1'b1 ) : Multiplier;

Temp <= 16'd0;

i<=i + 1'b1;

end

1: // Multipling

if( Mer == 0) i <= i+1'b1;

else begin Temp <= Temp + Mcand; Mer <= Mer- 1'b1; end

2:beginisDone <=1'b1;i <= i + 1'b1; end

3:begin isDone<= 1'b0; i <=2'd0; end

endcase

assign Done_Sig =isDone;

assign Product= isNeg? ( ~Temp + 1'b1 ) : Temp;

endmodule

booth乘法器

module booth_multiplier_module

(

input CLK,

? input RSTn,

?input Start_Sig,

? input [7:0]A,

input[7:0]B,

output Done_Sig,

output [15:0]Product,

?output[7:0]SQ_a,

output [7:0]SQ_s,

? output [16:0]SQ_p

);

reg [3:0]i;

? reg [7:0]a; // resultof A

? reg [7:0]s; //reverse resultof A

? reg [16:0]p;//p空间,16+1位

reg [3:0]X;?//指示n次循环

? reg isDone;

?always @ ( posedgeCLKor negedgeRSTn )

if( !RSTn )

begin

???i<=4'd0;

???a<= 8'd0;

???s <=8'd0;

??p <=17'd0;

???X<= 4'd0;

???isDone <=1'b0;

??end

elseif(Start_Sig)

?case(i)

0:

?begin a<= A; s <=( ~A + 1'b1 );p<= { 8'd0, B , 1'b0 }; i <= i + 1'b1;end

1:

???if( X ==8 ) begin X<= 4'd0; i<= i +4'd2; end

??elseif(p[1:0] == 2'b01 ) begin p<= {p[16:9] + a , p[8:0] };i <= i + 1'b1; end

?else if( p[1:0] == 2'b10 )begin p<= { p[16:9] + s ,p[8:0]}; i <=i + 1'b1; end

???elsei <= i + 1'b1; //00和11,无操作

??2:

begin p <= { p[16], p[16:1] }; X <= X + 1'b1; i <= i - 1'b1; end //右移,最高位补0 or 1.

??3:

??begin isDone <= 1'b1; i<= i+1'b1;end

?4:

??begin isDone <= 1'b0; i <= 4'd0;end

endcase

? assignDone_Sig= isDone;

assign Product= p[16:1];

endmodule

除法器

moduledivider_module

(

input CLK,

input RSTn,

input Start_Sig,

input [7:0]Dividend,

input [7:0]Divisor,

outputDone_Sig,

output [7:0]Quotient,

output [7:0]Reminder,

);

reg[3:0]i;

reg [7:0]Dend;

reg [7:0]Dsor;

reg[7:0]Q;

reg[7:0]R;

regisNeg;

reg isDone;

always @( posedge CLKor negedge RSTn )

if( !RSTn )

begin

i <= 4'd0;

Dend <= 8'd0;

Dsor <= 8'd0;

Q <= 8'd0;

isNeg <= 1'b0;

isDone <= 1'b0;

end

else if( Start_Sig )

case( i )

0:

begin

Dend<= Dividend[7] ? ~Dividend+ 1'b1 : Dividend;

Dsor <=Divisor[7] ? Divisor : ( ~Divisor +1'b1 );

??isNeg <=Dividend[7] ^Divisor[7];

i <= i + 1'b1;

end

1: if( Divisor > Dend)

beginQ <= isNeg ? ( ~Q + 1'b1): Q; i <=i+ 1'

b1; end

else begin Dend<= Dend + Dsor;Q <

=Q + 1'b1;end

2:beginisDone <= 1'b1;i<= i +1'b1; end 3: begin isDone <= 1'b0; i <= 4'd0;end

endcase

assignDone_Sig= isDone;

assignQuotient =Q;

assignReminder= Dend;

endmodule

除法器2

modulediv(a,b,clk,result,yu)

input[3:0]a,b;

outputreg[3:0] result,yu;

input clk;reg[1:0]state;reg[3:0] m,n;

parameter S0=2'b00,S1=2'b01,S2=2'b10;

always@(posedge clk)

begin case(state)

S0: begin if(a>b) beginn<=a-b;m<=4'b0001; state<=S1;end

else begin m<=4'b0000;n<=a; state<=S2; end

end

S1: begin if(n>=b) begin m<=m+1;n<=n-b;state<=S1;end

else begin state<=S2;end

end

S2:beginresult<=m;yu<=n;state<=S0;end

defule:state<=S0;

endcase

end

endmodule

13、一个可预置初值的7进制循环计数器

①verilog

module count(clk,reset,load,date,out);

input load,clk,reset;

input[3:0] date;

output reg[3:0]out;

parameter WIDTH=4'd7;

always@(clkor reset)

begin

if(reset) out<=4'd0;

else if(load)?out<=date;

?elseif(out==WIDTH-1) out<=4'd0;

else ?out<=out+1;

end

endmodule

Johnson计数器

约翰逊(Johnson)计数器又称扭环计数器,是一种用n位触发器来表示2n个状态的计数器。它与环形计数器不同,后者用n位触发器仅可表示n个状态。n位二进制计数器(n为触发器的个数)有2^n个状态。若以四位二进制计数器为例,它可表示16个状态。

“0000-1000-1100-1110-1111-0111-0011-0001-0000-1000……”

module Johnson(input clk,input clr,output reg[N-1:0]q);

always@(posedgeclk or negedge clr)

if(!clr)?q<={N{1’b0}}

else if(!q[0]) q<={1’b1,q[N-1:1]};

else??q<={1’b0,q[N-1]:1}];

endmodule

任意分频,占空比不为50%

always(clk)

?begin?if(count==x-1) count<=0;

??else?count<=count+1;?end

assign clkout=count[y]?//y一般用count的最高位

偶数分频(8分频,占空比50%)(计数至n-1,翻转)

module count5(reset,clk,out)

input clk,reset; output out;

reg[1:0]count;

always@(clk)

if(reset) begincount<=0; out<=0; end

else if(count==3)?begin count<=0;out<=!out: end

else count<=count+1;

endmodule

奇数分频电路(占空比50%)。

module count5(reset,clk,out)

input clk,reset;?output out;

reg[2:0] m,n;

reg count1;regcount2;

always@(posedge clk)

begin

?if(reset) ?beginm<=0;count1<=0;end

?else?begin if(m==4)m<=0; else m<=m+1; //“4”为分频数NUM-1,NUM=5

if(m<2)count1<=1; elsecount1<=0;?end

end

always@(negedgeclk)

begin

if(reset) begin?n<=0;count2<=0;end

else begin?if(n==4) n<=0; else n<=n+1;

if(n<2)count2<=1;else count2<=0;?end

end

assign out=count1|count2;

半整数分频

module fdiv5_5(clkin,clr,clkout)

inputclkin,clr;?outputreg clkout;

reg clk1; wire clk2; integer count;

xorxor1(clk2,clkin,clk1)

always@(posedgeclkout or negedgeclr)

begin?if(~clr) begin clk1<=1’b0; end

elseclk1<=~clk1;

end

always@(posedge clk2 or negedgeclr)

begin?if(~clr)

begin count<=0; clkout<=1’b0; end

?elseif(count==5)

??begin count<=0; clkout<=1’b1; end

?elsebegin count<=count+1; clkout<=1’b0; end

end

endmodule

小数分频

N=M/P.N为分配比,M为分频器输入脉冲数,P为分频器输出脉冲数。

N=(8×9+9×1)/(9+1)=8.1先做9次8分频再做1次9分频。

module fdiv8_1(clkin,rst,clkout)

input clkin,rst; output reg clkout;

reg[3:0] cnt1,cnt2;

always@(posedgeclkinorposedge rst)

begin if(rst) begin cnt1<=0;cnt2<=0;clkout<=0; end

elseif(cnt1<9) //cnt1, 0~8 begin

if(cnt2<7) begin cnt2<=cnt2+1;clkout<=0; end

else begin cnt2<=0;cnt1<=cnt1+1;clkout<=1;end

end

elsebegin //cnt1, 9

if(cnt2<8) begin cnt2<=cnt2+1;clkout<=0; end

else begin cnt2<=0;cnt1<=0;clkout<=1;end

end

end

endmodule

串并转换

module p2s(clk,clr,load,pi,so)

inputclk,clr,load;

input[3:0] pi;

output so;

reg[3:0]r;

always@(posedgeclk or negedgeclr)

if(~clr)?r<=4'h0;

else if(load) r<=pi;

else r<={r, 1'b0}; // or r<<1;

assignso=r[3];

endmodule

module s2p(clk,clr,en,si,po)

inputclk,clr,en,si;

output[3:0] po;

always@(posedge clk or negedge clr)

if(~clr)?r<=8’ho;

else r<={r,si};

assign po=(en) ?r :4’h0;

endmodule

b) 试用VHDL或VERILOG、ABLE描述8位D触发器逻辑。module dff(q,qn,d,clk,set,reset)

input[7:0] d,set;

input clk,reset;

output reg[7:0] q,qn;

always @(posedge clk)

begin

if(reset) begin?q<=8’h00; qn<=8’hFF; end

else if(set) begin q<=8’hFF; qn<=8’h00; endelse begin q<=d; qn<=~d;end

end

endmodule

序列检测“101”

module xulie101(clk,clr,x,z);

input clk,clr,x;output reg z;

reg[1:0]state,next_state;

parameter s0=2'b00,s1=2'b01,s2=2'b11,s3=2'b10;

always @(posedge clk or posedge clr)

begin if(clr) state<=s0;

elsestate<=next_state;

end

always @(state or x)

begin

case(state)

s0:begin if(x)?next_state<=s1;

?? else next_state<=s0;end

s1:begin if(x)?next_state<=s1;

?else next_state<=s2;end

?s2:begin if(x)?next_state<=s3;

??else next_state<=s0;end

?s3:beginif(x) next_state<=s1;

?elsenext_state<=s2;end

?default: next_state<=s0;

endcase

end

always @(state)

begin case(state)

??s3:z=1;

?default:z=0;

?endcase

end

endmodule

?

按键消抖

1.采用一个频率较低的时钟,对输入进行采样,消除抖动。

module switch(clk,keyin,keyout)

parameterCOUNTWIDTH=8;

input clk,keyin; output reg keyout; reg[COUNTWIDTH-1:0]counter; wireclk_use; //频率较低的时钟

assignclk_use=counter[COUNTWIDTH-1];

always@(posegde clk)

counter<=counter+1’b1;

always@(posedge clk_use)

?keyout<=keyin;

endmodule

2.module switch(clk,keyin,keyout)

parameter COUNTWIDTH=8;

input clk,keyin;?outputregkeyout;reg[COUNTWIDTH-1:0]counter; initial ?counter<=0,keyout<=0,keyin<=0;

always@(posegde clk)

if(keyin=1)begin key_m<=keyin, counter<=counter+1;end

?else counter<=0;

?if(keyin&&counter[m]) keyout<=1; //m定义时延

endmodule

数码管显示

modulenumber_mod_module ??//分别取得数字的十位和个位

(CLK, RSTn, Number_Data, Ten_Data, One_Data);

inputCLK;

input RSTn;

? input[7:0]Number_Data;

output[3:0]Ten_Data;

output[3:0]One_Data;

?reg [31:0]rTen;

?reg [31:0]rOne;

always @ (posedge CLKornegedge RSTn)

if( !RSTn)

begin

???rTen<= 32'd0;

???rOne <= 32'd0;

?end

?else

?begin

??rTen <= Number_Data / 10;

??rOne <= Number_Data%10;

?end

?assign Ten_Data =rTen[3:0];

?assign One_Data =rOne[3:0];

endmodule

moduleled(CLK, Ten_Data, One_Data,led0, led1);?//数码管显示input [3:0] Ten_Data,One_Data;

?inputCLK;

output [7:0] led0,led1;

?reg [7:0]led0, led1;

always@( posedgecp_50)

begin

???casez (One_Data)

??4'd0 : led0= 8'b1100_0000;

???4'd1 : led0 = 8'b1111_1001;

?4'd2: led0 =8'b1010_0100;

??4'd3 : led0 =8'b1011_0000;

???4'd4 : led0 = 8'b1001_1001;

???4'd5 : led0 = 8'b1001_0010;

?????4'd6: led0 = 8'b1000_0010;

???4'd7 :led0 =8'b1111_1000;

??4'd8 : led0 = 8'b1000_0000;

???4'd9:led0= 8'b1001_0000;?

????default: led0 = 8'b1111_1111; ?

?endcase

???casez (Ten_Data)

????4'd0 :led1=8'b1100_0000;

???4'd1 : led1 = 8'b1111_1001;

??4'd2 : led1=8'b1010_0100;

???4'd3 :led1 = 8'b1011_0000;

?4'd4 : led1 = 8'b1001_1001;

???4'd5 :led1 = 8'b1001_0010;

????4'd6 : led1= 8'b1000_0010;

?4'd7 : led1 =8'b1111_1000;

?4'd8 : led1 = 8'b1000_0000;

????4'd9: led1 = 8'b1001_0000;?

????default: led0= 8'b1111_1111; ??

?endcase

??end

endmodule

5. fifo控制器.

FIFO存储器FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。在系统设计中,以增加数据传输率、处理大量数据流、匹配具有不同传输率的系统为目的而广泛使用FIFO存储器,从而提高了系统性能.

FIFO参数:

FIFO的宽度,thewidth,指FIFO一次读写操作的数据位;

FIFO深度,THE DEEPTH,指FIFO可以存储多少个N位的数据;

满标志,FIFO已满或将要满时送出的一个信号,以阻止FIFO的血操作继续向FIFO中写数据而造成溢出(overflow);

空标志,阻止FIFIO的读操作;

module fifo_module

(

input CLK,

input RSTn,

input Write_Req,

input [7:0]FIFO_Write_Data,

inputRead_Req,

output[7:0]FIFO_Read_Data,

output Full_Sig,

output Empty_Sig,

/**********************/

output [7:0]SQ_rS1,

output[7:0]SQ_rS2,

output [7:0]SQ_rS3,

output [7:0]SQ_rS4,

output [2:0]SQ_Count

/**********************/

);

/************************************/

parameter DEEP=3'd4;

/************************************/

reg [7:0]rShift [DEEP:0];

reg [2:0]Count;

reg [7:0]Data;

always @ ( posedge CLKor negedge RSTn)

if( !RSTn )

begin

rShift[0] <= 8'd0; rShift[1]<= 8'd0; rShift[2] <=8'd0;

rShift[3]<= 8'd0; rShift[4] <= 8'd0;

Count <=3'd0;

Data <=8'd0;

end

elseif( Read_Req && Write_Req&&Count <DEEP && Count > 0 ) begin

rShift[1] <= FIFO_Write_Data;

rShift[2] <= rShift[1];

rShift[3] <= rShift[2];

rShift[4] <=rShift[3];

Data <= rShift[ Count];

end

else if( Write_Req &&Count < DEEP )

begin

rShift[1] <= FIFO_Write_Data;

rShift[2]<= rShift[1];

rShift[3] <= rShift[2];

rShift[4] <= rShift[3];

Count <= Count+1'b1;

end

else if( Read_Req &&Count>0)

begin

Data <= rShift[Count];

Count <= Count - 1'b1;

end

/************************************/

assign FIFO_Read_Data= Data;

assign Full_Sig = (Count == DEEP ) ?1'b1 : 1'b0;

assignEmpty_Sig= (Count== 0 )? 1'b1 : 1'b0;

/************************************/

assign SQ_rS1= rShift[1];

assign SQ_rS2 = rShift[2];

assignSQ_rS3= rShift[3];

assign SQ_rS4 = rShift[4];

assign SQ_Count =Count;

/************************************/

Endmodule

fifi2 (指针控制)

module FIFO(date,q,clr,clk,we,re,ff,ef);

parameter WIDTH=8,DEEPTH=8,ADDR=3;

inputclk,clr;

input we,re;

input[WIDTH-1:0] date;

outputff,ef;

output reg[WIDTH-1:0] q;

reg[WIDTH-1:0] mem_date[DEEPTH-1:0];

reg[ADDR-1:0] waddr,raddr; reg ff,ef;

always@(posedge clkor negedgeclr) //写地址

begin if(!clr) waddr=0;

?else if(we==1&&ff==0) waddr=waddr+1;

?elseif(we==1&&ff==0&&waddr==7) waddr=0;

end

always@(posedge clk)

begin if(we&&!ff) mem_date[waddr]=date; end

always@(posedgeclk or negedge clr)?//读地址

begin if(!clr)raddr=0;

?elseif(re==1&&ef==0) raddr=waddr+1;

??elseif(re==1&&ef==0&&raddr==7)raddr=0;

end

always@(posedge clk)

begin if(re&&!ef) q=mem_date[raddr];?end

always@(posedgeclk or negedgeclr)

begin if(!clr) ff=1'b0;

??else if((we & !re) && ((waddr==raddr-1) || ((waddr==DEEPTH-1) &&(raddr==1'b0))))

??ff=1'b1;

?else ff=1'b0;

end

always@(posedge clk or negedge clr)

beginif(!clr)ef=1'b0;

?else if(((!we&re)&&(waddr==raddr+1)||((raddr==DEEPTH-1)&&(waddr==1'b0))))

?ef=1'b1;

?else ef=1'b0;

end

endmodule

交通信号灯

module jiaotong(clk,reset,lamp,downtime);

inputclk,reset;

output reg [5:0]lamp;

output[6:0]downtime;

reg [6:0]timedown;

reg[1:0]state;

reg [31:0]count1;

always@(clk)//产生0~100s的计时

begin

if(reset) count1<=0;//计数器必须赋初值,否者无法进行计数

elseif(count1==32'd100) count1<=0;

else count1<=count1+1;

end

always@(clkor count1)

begin

if(reset) state<=0;

else if(count1>=32'd1&&count1<=32'd45)state=0;

else if(count1>=32'd46&&count1<=32'd50) state=1;

else if(count1>=32'd51&&count1<=32'd95) state=2;

elseif(count1>=32'd96&&count1<=32'd100) state=3;

end

always@(clk)

begin

case(state)//state只能在一个过程快内被赋值,所以其复位操作放在前一个always块中

0:beginlamp<=6'b100001;timedown<='d45-count1;end

1:begin lamp<=6'b010001;timedown<='d50-count1;end

2:begin lamp<=6'b001100; timedown<='d95-count1;end

3:beginlamp<=6'b001010; timedown<='d100-count1;end

endcase

end

assign downtime=timedown;

endmodule

仿真激励:

`timescale 1ms/1ms

`include "jiaotong.v"

module jiaotong_tp;

reg clk; regreset;

wire [5:0]lamp;

wire [6:0]downtime; //输出需用wire型

jiaotong u1(

.clk(clk),

.reset(reset),

.lamp(lamp),

.downtime(downtime)

);

initial

begin

clk=0; reset=0;

#500 reset=1;

#500 reset=0; //需统一放入begin-end块中

end

always #500 clk=~clk;

initial $monitor($time,,,"clk=%bcount1=%d",clk,count1); //只是在调试过程中监控count1的计数状态

endmodule

相关主题
相关文档
最新文档