Verilog的八个经典入门例题
前言
西安电子科技大学大三上学期硬件描述语言与可编程逻辑设计上机作业,本文作者采用vivado软件编译,Vivado自带的Simulation工具仿真,效果完全等同于Quartus编译+Modelsim仿真的组合
提示:以下是本篇文章正文内容,提供的程序仅供参考
一、7人表决器设计
题目内容:设计一个表决器,实现功能大于3人同意,表决通过,输出“1’b1”,否则输出“1’b0”。
源程序(示例):
module vote_7in(
input a,b,c,d,e,f,g,
output out
);
assign out = (a+b+c+d+e+f+g >3)?1:0;
endmodule
测试程序(示例):
`timescale 1ns / 1ns
module vote_7in_tb;
reg a,b,c,d,e,f,g;
wire out;
vote_7in U1(.a(a),.b(b),.c(c),.d(d),.e(e),.f(f),.g(g),.out(out));
initial
begin
{a,b,c,d,e,f,g} = 7'b0;
#5 a = 1'b1;
#5 b = 1'b1;
#5 c = 1'b1;
#5 d = 1'b1;
#5 e = 1'b1;
#5 f = 1'b1;
#5 g = 1'b1;
end
endmodule
仿真波形截图(示例):
二、8位的ALU设计
题目内容: 设计一个8位的ALU(算术逻辑单元),该单元具有两个输入数据a,b和一个输入操作符Oper及输出数据c_out, sum,并且还具有下表所示的功能。
操作符 | 功能 |
---|---|
Add | a+b |
Subtract | a-b |
Subtract_a | b-a |
Or | a | b |
And | a&b |
Xor | a^b |
Xnor | a~^b |
源程序(示例):
/*仅考虑无符号情况*/
module alu_8bit(
input[7:0] a,b,
input[2:0]Oper,
output reg c_out,
output reg[7:0] sum
);
always@(a or b or Oper)
begin
case(Oper)
3'b000: {c_out,sum} = a + b;
3'b001: {c_out,sum} = a - b;
3'b010: {c_out,sum} = b - a;
3'b011: {c_out,sum} = a | b;
3'b100: {c_out,sum} = a & b;
3'b101: {c_out,sum} = a ^ b;
3'b110: {c_out,sum} = a ~^ b;
default: {c_out,sum} = 9'bx;
endcase
end
endmodule
测试程序(示例):
`timescale 1ns / 1ns
module alu_8bit_tb;
reg[7:0] a,b;
reg[2:0] Oper;
wire c_out;
wire[7:0] sum;
alu_8bit u1(.a(a),.b(b),.Oper(Oper),.c_out(c_out),.sum(sum));
initial
begin
a = 8'b01110000; b = 4'b11110011; Oper = 3'b0;
#5 Oper = 3'b000;
#5 Oper = 3'b001;
#5 Oper = 3'b010;
#5 Oper = 3'b011;
#5 Oper = 3'b100;
#5 Oper = 3'b101;
#5 Oper = 3'b110;
#5 Oper = 3'b111;
end
endmodule
仿真波形截图(示例):
三、JK触发器的设计
题目内容: 编写Verilog代码使之能正确描述下表所示的1bit JK触发器功能,其中Q+表示在时钟上升沿到来后的Q值。要求该触发器还具有异步复位的功能。
J | K | Q+ |
---|---|---|
0 | 0 | Q |
1 | 0 | 1 |
0 | 1 | 0 |
1 | 1 | ~Q |
源程序(示例):
module jk_ff(j,k,q,clk,rst);
input j,k,clk,rst;
output reg q;
always@(posedge clk or posedge rst)
begin
if(rst == 1'b1)
q = 0;
else
case({j,k})
2'b00:q = q;
2'b10:q = 1;
2'b01:q = 0;
2'b11:q = ~q;
endcase
end
endmodule
测试程序(示例):
`timescale 1ns/1ns
module jk_ff_tb;
reg j,k,clk,rst;
wire q;
jk_ff u1(.j(j),.k(k),.clk(clk),.rst(rst),.q(q));
always #5 clk = ~clk;
initial
begin
rst = 0; clk = 0; j = 1; k = 0;
#10 j=0;k=0;
#10 j=1;k=0;
#10 j=0;k=1;
#10 j=1;k=1;
#15 rst = 1;
#10 j=0;k=0;
#10 j=1;k=0;
#10 j=0;k=1;
#10 j=1;k=1;
end
endmodule
仿真波形截图(示例):
四、环形计数器
题目内容: 设计下图所示寄存顺序的环形计数器,异步复位,复位时计数器中的值为4’b0001。
要求:(1)用参数定义此计数器的位宽;
(2)仿真测试对象为8bit的环形计数器;
0 | 0 | 0 | 1 |
---|---|---|---|
0 | 0 | 1 | 0 |
0 | 1 | 0 | 0 |
1 | 0 | 0 | 0 |
0 | 1 | 0 | 0 |
0 | 0 | 1 | 0 |
0 | 0 | 0 | 1 |
源程序(示例):
module ring_count(reset, clk, count);
parameter width = 4;
input reset, clk;
output reg[width - 1:0] count;
integer I;
always@(posedge clk or posedge reset)
begin
if(reset == 1'b1)
begin
count <= 4'b0001;
I <= 0;
end
else
begin
if(I<width - 1)
begin
count <= {count[2:0],count[width - 1]};
I <= I + 1;
end
else if(I<5&&I>=width - 1)
begin
count <= {count[0],count[width - 1:1]};
I <= I + 1;
end
else
begin
count <= {count[0],count[width - 1:1]};
I <= 0;
end
end
end
endmodule
测试程序(示例):
`timescale 1ns/1ns
module ring_count_tb;
reg clk,reset;
wire [7:0] count;
ring_count u1(.reset(reset),.clk(clk),.count(count));
always #5 clk = ~clk;
initial
begin
clk <= 1'b0;
reset <= 1'b1;
#15 reset = 1'b0;
#100 reset = 1'b1;
end
endmodule
仿真波形截图(示例):
五、二进制整数除法器设计
要求:(1)分析除法器工作原理,不能使用整除运算符/ 和求余运算符% ;
(2)设被除数位数=8,除数位数=4
(3)输出商和余数
源程序(示例):
/*二进制无符号整数除法*/
module divider_2bit(a,b,c,d);
input [7:0]a;//a为被除数
input [3:0]b;//b为除数
output reg[7:0]c;//c为商
output reg[3:0]d;//d为余数
reg[15:0] temp_a=0;
reg[7:0] temp_c=0;
integer I;
always@(a or b)
begin
temp_a = a;
for(I=0;I<9;I=I+1)//效果等同于repeat(9),只有循环次数确定的for、while、repeat语句才可综合,否则不可综合
begin
temp_c = temp_c<<1;//移位运算符的结果是一串数,并不能改变移位对象的值
if(temp_a[15:8]>=b)
begin
temp_c = temp_c + 1'b1;
temp_a[15:8] = temp_a[15:8] - b;
temp_a = temp_a<<1;//效果等同于temp_a = {temp_a[14:0],1'b0};切记使用位拼接运算符要注明位宽
end
else
temp_a = temp_a<<1;//不可写作temp_a = {temp_a[14:0],0};因为0没有注明位宽
end
c <= temp_c;
d <= temp_a[12:9];
end
endmodule
测试程序(示例):
`timescale 1ns / 1ns
module divider_2bit_tb;
reg[7:0] a;
reg[3:0] b;
wire[7:0]c;
wire[3:0]d;
divider_2bit u1(.a(a),.b(b),.c(c),.d(d));
initial
begin
a = 8'b0001_1011;
b = 4'b0101;
#100
a = 8'b1001_1011;
b = 4'b0001;
#100
a = 8'b0000_0011;
b = 4'b1101;
#100
a = 8'd250;
b = 4'd15;
#100
a = 8'd6;
b = 4'd3;
#100
a = 8'd97;
b = 4'd13;
end
endmodule
仿真波形截图(示例):
六、排序任务
设a,b,c,d四个数,按从小到大的顺序重新排列并输出到ra,rb,rc,rd中。
要求:(1)需在Verilog HDL描述中使用任务(task)。
源程序(示例):
module sort_task(a,b,c,d,ra,rb,rc,rd);
parameter width = 4;
input [width-1:0] a,b,c,d;
output reg[width-1:0] ra,rb,rc,rd;
always@(a or b or c or d)
begin
sort(a,b,c,d,ra,rb,rc,rd);
end
task sort;
input [width-1:0] a,b,c,d;
output reg[width-1:0] ra,rb,rc,rd;
reg [width-1:0]temp;
integer i,j;
reg [width-1:0]data[3:0];
begin
data[0] = a;
data[1] = b;
data[2] = c;
data[3] = d;
for(i=0;i<3;i=i+1)
begin
for(j=0;j<3-i;j=j+1)
begin
if(data[j]>data[j+1])
begin
temp = data[j+1];
data[j+1] = data[j];
data[j] = temp;
end
end
end
ra = data[0];
rb = data[1];
rc = data[2];
rd = data[3];
end
endtask
endmodule
测试程序(示例):
`timescale 1ns / 1ns
module sort_task_tb;
parameter width = 4;
reg[width-1:0] a,b,c,d;
wire[width-1:0] ra,rb,rc,rd;
sort_task u1(.a(a),.b(b),.c(c),.d(d),.ra(ra),.rb(rb),.rc(rc),.rd(rd));
initial
begin
a <= 4'd4;
b <= 4'd3;
c <= 4'd2;
d <= 4'd1;
#500
a <= 4'd0;
b <= 4'd7;
c <= 4'd3;
d <= 4'd5;
end
endmodule
仿真波形截图(示例):
七、简易频率计
设计一个8 位数字显示的简易频率计
要求:
①能够测试10Hz~10MHz 方波信号;
②电路输入的基准时钟为1Hz,要求测量值以8421BCD 码形式输出;
③系统有复位键;
④采用分层次分模块的方法;
源程序(示例):
module freq_cnt(clk_1Hz, fin, rst, d0, d1, d2, d3, d4, d5, d6, d7);
input clk_1Hz;
input fin;
input rst;
output[3:0] d0, d1, d2, d3, d4, d5, d6, d7;
wire[3:0] q0, q1, q2, q3, q4, q5, q6, q7;
//wire[3:0] d0, d1, d2, d3, d4, d5, d6, d7;
wire[3:0] en_out0,en_out1,en_out2,en_out3,en_out4,en_out5,en_out6,en_out7;
wire count_en;
wire latch_en;
wire clear;
control u_control(.clk_1Hz(clk_1Hz), .rst(rst), .count_en(count_en),
.latch_en(latch_en), .clear(clear));
counter_10 counter0(.en_in(count_en), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out0), .q(q0));
counter_10 counter1(.en_in(en_out0), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out1), .q(q1));
counter_10 counter2(.en_in(en_out1), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out2), .q(q2));
counter_10 counter3(.en_in(en_out2), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out3), .q(q3));
counter_10 counter4(.en_in(en_out3), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out4), .q(q4));
counter_10 counter5(.en_in(en_out4), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out5), .q(q5));
counter_10 counter6(.en_in(en_out5), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out6), .q(q6));
counter_10 counter7(.en_in(en_out6), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out7), .q(q7));
ulatch u_latch(.clk_1Hz(clk_1Hz),.rst(rst),.latch_en(latch_en),
.q0(q0),.q1(q1),.q2(q2),.q3(q3),.q4(q4),.q5(q5),.q6(q6),.q7(q7),
.d0(d0),.d1(d1),.d2(d2),.d3(d3),.d4(d4),.d5(d5),.d6(d6),.d7(d7));
endmodule
module control(clk_1Hz, rst, count_en, latch_en, clear);
input clk_1Hz;
input rst;
output count_en;
output latch_en;
output clear;
reg[1:0] state;
reg count_en;
reg latch_en;
reg clear;
always @(posedge clk_1Hz or negedge rst)
if(!rst)
begin
state <= 2'd0;
count_en <= 1'b0;
latch_en <=1'b0;
clear <= 1'b0;
end
else
begin
case(state)
2'd0:
begin
count_en <= 1'b1;
latch_en <=1'b0;
clear <= 1'b0;
state <= 2'd1;
end
2'd1:
begin
count_en <= 1'b0;
latch_en <=1'b1;
clear <= 1'b0;
state <= 2'd2;
end
2'd2:
begin
count_en <= 1'b0;
latch_en <=1'b0;
clear <= 1'b1;
state <= 2'd0;
end
default:
begin
count_en <= 1'b0;
latch_en <=1'b0;
clear <= 1'b0;
state <= 2'd0;
end
endcase
end
endmodule
module counter_10(en_in, rst, clear, fin, en_out, q);
input en_in;
input rst;
input clear;
input fin;
output en_out;
output[3:0] q;
reg en_out;
reg[3:0] q;
always@ (posedge fin or negedge rst)
if(!rst)
begin
en_out <= 1'b0;
q <= 4'b0;
end
else if(en_in)
begin
if(q == 4'b1001)
begin
q <= 4'b0;
en_out <= 1'b1;
end
else
begin
q <= q + 1'b1;
en_out <=1'b0;
end
end
else if(clear)
begin
q <= 4'b0;
en_out <= 1'b0;
end
else
begin
q <= q;
en_out <=1'b0;
end
endmodule
module ulatch(clk_1Hz, latch_en, rst, q0, q1, q2, q3, q4, q5, q6, q7,
d0, d1, d2, d3, d4, d5, d6, d7);
input clk_1Hz, latch_en, rst;
input[3:0] q0, q1, q2, q3, q4, q5, q6, q7;
output[3:0] d0, d1, d2, d3, d4, d5, d6, d7;
reg[3:0] d0, d1, d2, d3, d4, d5, d6, d7;
always@ (posedge clk_1Hz or negedge rst)
if(!rst)
begin
d0 <= 4'b0; d1 <= 4'b0; d2 <= 4'b0; d3 <= 4'b0; d4 <= 4'b0;
d5 <= 4'b0; d6 <= 4'b0; d7 <= 4'b0;
end
else if(latch_en)
begin
d0 <= q0; d1 <= q1; d2 <= q2; d3 <= q3; d4 <= q4;
d5 <= q5; d6 <= q6; d7 <= q7;
end
else
begin
d0 <= d0; d1 <= d1; d2 <= d2; d3 <= d3; d4 <= d4;
d5 <= d5; d6 <= d6; d7 <= d7;
end
endmodule
测试程序(示例):
`timescale 1ns/1ps
//测试模块
module freq_cnt_tb;
parameter CLK_1HZ_DELAY = 5_0000_0000; //1Hz基准信号
parameter FIN_DELAY = 100; //5MHz待测信号
reg clk_1Hz;
reg fin;
reg rst;
wire[3:0] d0, d1, d2, d3, d4, d5, d6, d7;
initial
begin
rst =1'b0;
#1 rst = 1'b1;
end
initial
begin
fin = 1'b0;
forever
#FIN_DELAY fin = ~fin;
end
initial
begin
clk_1Hz = 1'b0;
forever
#CLK_1HZ_DELAY clk_1Hz = ~clk_1Hz;
end
freq_cnt freDetect1(.clk_1Hz(clk_1Hz), .rst(rst), .fin(fin),
.d0(d0), .d1(d1), .d2(d2), .d3(d3), .d4(d4), .d5(d5), .d6(d6), .d7(d7));
endmodule
仿真波形截图(示例):
八、序列检测器
要求:
(1)在每一个时钟下降沿检查输入数据,当输入数“10011”时,输出asm被置为1;其余情况asm为0。
(2)画出fsm(有限状态机);
源程序(示例):
module seq_detector(clk,ain,asm);
input clk,ain;
output reg asm;
reg[4:0] q;
q = 5'b00000;
always@(negedge clk) q <= {q[3:0],ain};
always@(negedge clk)
if(q == 5'b10011) asm = 1;
else asm = 0;
endmodule
测试程序(示例):
`timescale 1ns/1ps
module seq_detector_tb;
wire asm,ain;
reg clk;
reg[19:0] arr;
seq_detector U0(.clk(clk),.ain(ain),.asm(asm));
initial
begin
clk = 0;
arr = 20'b_01001_11010_11001_10010;
#500 $stop;
end
always #5 clk=~clk;
always @(negedge clk) arr = {arr[0],arr[19:1]};
assign ain = arr[0];
endmodule
仿真波形截图(示例):