当前位置:文档之家› 常见面试笔试题verilog程序库

常见面试笔试题verilog程序库

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

常见面试笔试题verilog程序库

加减法

module addsub

( input [7:0] dataa,

input [7:0] datab,

input add_sub, // if this is 1, 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;"

else result <= 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。至于溢出的最高位能够无视掉。

乘法器

module mult(outcome,a,b);

parameter SIZE=8;

input[SIZE:1] a,b;

output reg[2*SIZE:1] outcome;

integer i;

always @(a or 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: begin isDone <= 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; // result of A

reg [7:0]s; // reverse result of A

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

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

reg isDone;

always @ ( posedge CLK or negedge RSTn )

if( !RSTn )

begin

i <= 4'd0;

a <= 8'd0;

s <= 8'd0;

p <= 17'd0;

X <= 4'd0;

isDone <= 1'b0;

end

else if( 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

else if( 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

else i <= 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

assign Done_Sig = isDone;

assign Product = p[16:1];

endmodule

除法器

module divider_module

(

input CLK,

input RSTn,

input Start_Sig,

input [7:0]Dividend,

input [7:0]Divisor,

output Done_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;

reg isNeg;

reg isDone;

always @ ( posedge CLK or 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 )

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

else begin Dend <= Dend + Dsor; Q <= Q +

1'b1; end

2: begin isDone <= 1'b1; i <= i + 1'b1; end

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

endcase

assign Done_Sig = isDone;

assign Quotient = Q;

assign Reminder = Dend;

endmodule

除法器2

module div(a,b,clk,result,yu)

input[3:0]a,b;

output reg[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) begin n<=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: begin result<=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@(clk or reset)

begin

if(reset) out<=4'd0;

else if(load) out<=date;

else if(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@(posedge clk 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) begin count<=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;reg count2;

always@(posedge clk)

begin

if(reset) begin m<=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; else count1<=0; end

end

always@(negedge clk)

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)

input clkin,clr; output reg clkout;

reg clk1; wire clk2; integer count;

xor xor1(clk2,clkin,clk1)

always@(posedge clkout or negedge clr)

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

else clk1<=~clk1;

end

always@(posedge clk2 or negedge clr)

begin if(~clr)

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

else if(count==5)

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

else begin 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@(posedge clkin or posedge rst)

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

else if(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

else begin //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)

input clk,clr,load;

input [3:0] pi;

output so;

reg[3:0] r;

always@(posedge clk or negedge clr)

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

else if(load) r<=pi;

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

assign so=r[3];

endmodule

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

input clk,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; end else 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;

else state<=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:begin if(x) next_state<=s1;

else next_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)

parameter COUNTWIDTH=8;

input clk,keyin;output reg keyout; reg[COUNTWIDTH-1:0] counter;

wire clk_use;//频率较低的时钟

assign clk_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;output reg keyout; 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

数码管显示

module number_mod_module //分别取得数字的十位和个位

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

input CLK;

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 CLK or negedge 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

module led(CLK, Ten_Data, One_Data,led0, led1); //数码管显示

input [3:0] Ten_Data, One_Data;

input CLK;

output [7:0] led0, led1;

reg [7:0] led0, led1;

always @( posedge cp_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的宽度,the width,指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,

input Read_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 CLK or 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

else if( 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;

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

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

assign SQ_rS1 = rShift[1];

assign SQ_rS2 = rShift[2];

assign SQ_rS3 = rShift[3];

assign SQ_rS4 = rShift[4];

assign SQ_Count = Count;

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

Endmodule

fifi 2 (指针控制)

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

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

input clk,clr;

input we,re;

input[WIDTH-1:0] date;

output ff,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 clk or negedge clr) //写地址begin if(!clr) waddr=0;

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

else if(we==1&&ff==0&&waddr==7) waddr=0; end

always@(posedge clk)

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

always@(posedge clk or negedge clr) //读地址begin if(!clr) raddr=0;

else if(re==1&&ef==0) raddr=waddr+1;

else if(re==1&&ef==0&&raddr==7) raddr=0;

end

always@(posedge clk)

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

always@(posedge clk or negedge clr)

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)

begin if(!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);

input clk,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; //计数器必须赋初值,否者无法进行计数

else if(count1==32'd100) count1<=0;

else count1<=count1+1;

end

always@(clk or 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;

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

end

always@(clk)

begin

case(state) //state只能在一个过程快内被赋值,因此其复位操作放在前一个always块中0:begin lamp<=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:begin lamp<=6'b001010; timedown<='d100-count1;end

endcase

end

assign downtime=timedown;

endmodule

仿真激励:

`timescale 1ms/1ms

`include "jiaotong.v"

module jiaotong_tp;

reg clk; reg reset;

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=%b count1=%d",clk,count1); //只是在调试过程中监控count1的计数状态

endmodule

相关主题
文本预览
相关文档 最新文档