1.写一套硬件描述语言,能够在指定的硬件平台上实现相应的功能;
2.设计定义(功能说明);
3.编写逻辑Design Sources(Verilog语言代码描述逻辑)、画逻辑图、使用IP核(封装好的逻辑);
4.分析综合工具Synthesis->run(由专业的EDA软件提供,如:Quartus、Vivado、ISE):对所写的逻辑描述内容进行分析,并得到逻辑门级别的电路内容;,目的:检查语法和逻辑是否错误。
5.功能仿真Simulation Sources(逻辑仿真)使用专门的仿真工具进行仿真,验证设计的逻辑是否可以实现;
6.布局布线Synthesis->Open Sysnthesized design ->Layout->I/P planning(设置引脚):在指定的器件上将设计的逻辑电路实现
7.分析性能:时序分析(耗时)、静态时序分析;
8.上板:下载到目标板上运行、查看运行结果;
简单流程总结:
1.设计定义;
2.设计输入
3.分析综合(EDA、Quartys、Vivado)
4.功能仿真(Modelsim)
5.布局布线(Quartys、Vivado)
6.分析性能(时序仿真Modelsim、静态时序分析Quartys、Vivado)
7.板级调试
例子1:二选一多路器
功能设计:
module mux2(a, b, sel, out ) ;
input a ;
input b ;
input sel ;
output out ;
//功能:二选一多路器
assign out = (sel ==1)?a:b;
endmodule
测试代码:
` timescale 1ns / 1ns
module mux2_tb();
reg s_a;
reg s_b;
reg sel;
wire out;
mux2 mux2_inst0(
. a(s_a),
. b(s_b),
. sel(sel),
. out(out)
);
initial begin
s_a = 0 ; s_b = 0 ; sel = 0 ;
#200;
s_a = 0 ; s_b = 0 ; sel = 1 ;
#200;
s_a = 0 ; s_b = 1 ; sel = 0 ;
#200;
s_a = 0 ; s_b = 1 ; sel = 1 ;
#200;
s_a = 1 ; s_b = 0 ; sel = 0 ;
#200;
s_a = 1 ; s_b = 0 ; sel = 1 ;
#200;
s_a = 1 ; s_b = 1 ; sel = 0 ;
#200;
s_a = 1 ; s_b = 1 ; sel = 1;
#200;
s_a =0 ; s_b = 1 ; sel = 1 ;
#200;
$stop;
end
endmodule
例子2:3-8译码器:
功能设计:
`timescale 1ns / 1ns
// Create Date: 2024/03/11 14:41:29
// Design Name: hilary
// Module Name: decoder_3_8
module decoder_3_8(
a, b, c, out
);
input a ;
input b ;
input c ;
output [7:0] out ;
reg [7:0] out ;
// 以always块描述的信号赋值,被赋值的对象必须定义为reg类型
// {a,b,c}将独立的信号变成一个信号,这种操作叫做位拼接
//wire [3:0]
//assign d = {a, 1'b0, c, d}
always@(*)begin
case( {a, b, c} )
3'b000 : out = 8'b0000_0001;
3'b001 : out = 8'b0000_0010;
3'b010 : out = 8'b0000_0100;
3'b011 : out = 8'b0000_1000;
3'b100 : out = 8'b0001_0000;
3'b101 : out = 8'b0010_0000;
3'b110 : out = 8'b0100_0000;
3'b111 : out = 8'b1000_0000;
endcase
end
endmodule
测试:
`timescale 1ns / 1ns
// Create Date: 2024/03/11 16:06:56
// Design Name: hilary
// Module Name: decoder_3_8_tb
module decoder_3_8_tb ;
reg s_a;
reg s_b;
reg s_c;
wire [7:0] out;
decoder_3_8 decoder_3_8(
. a(s_a) ,
. b(s_b),
. c(s_c),
. out(out)
);
initial begin
s_a = 0 ; s_b = 0 ; s_c = 0;
#200;
s_a = 0 ; s_b = 0 ; s_c = 1;
#200;
s_a = 0 ; s_b = 1 ; s_c = 0;
#200;
s_a = 0 ; s_b = 1 ; s_c = 1;
#200;
s_a = 1 ; s_b = 0 ; s_c = 0;
#200;
s_a = 1 ; s_b = 0 ; s_c = 1;
#200;
s_a = 1 ; s_b = 1 ; s_c = 0;
#200;
s_a = 1 ; s_b = 1 ; s_c = 1;
#200;
end
endmodule
例子3:4-16译码器:
功能设计:
// Create Date: 2024/03/11 19:07:55
// Design Name: hilary
// Module Name: decoder_4_16
module decoder_4_16(
a,
b,
c,
d,
out
);
input a;
input b;
input c;
input d;
output reg [15:0] out;
always@(*)begin
case({a,b,c,d})
4'd0 : out = 16'd0;
4'd1 : out = 16'd1;
4'd2 : out = 16'd2;
4'd3 : out = 16'd3;
4'd4 : out = 16'd4;
4'd5 : out = 16'd5;
4'd6 : out = 16'd6;
4'd7 : out = 16'd7;
4'd8 : out = 16'd8;
4'd9 : out = 16'd9;
4'd10 : out = 16'd10;
4'd11: out = 16'd11;
4'd12 : out = 16'd12;
4'd13 : out = 16'd13;
4'd14 : out = 16'd14;
4'd15 : out = 16'd15;
endcase
end
endmodule
测试:
`timescale 1ns/1ns
// Create Date: 2024/03/11 19:32:18
// Design Name: hilary
// Module Name: decoder_4_16_tb
module decoder_4_16_tb;
reg s_a;
reg s_b;
reg s_c;
reg s_d;
wire [15 : 0] out;
decoder_4_16 decoder_4_16(
.a(s_a),
.b(s_b),
.c(s_c),
.d(s_d),
.out(out)
);
initial begin
s_a = 0 ; s_b = 0 ; s_c = 0 ; s_d = 0 ;
#200;
s_a = 0 ; s_b = 0 ; s_c = 0 ; s_d = 1 ;
#200;
s_a = 0 ; s_b = 0 ; s_c = 1 ; s_d = 0 ;
#200;
s_a = 0 ; s_b = 0 ; s_c = 1 ; s_d = 1 ;
#200;
s_a = 0 ; s_b = 1 ; s_c = 0 ; s_d = 0 ;
#200;
s_a = 0 ; s_b = 1 ; s_c = 0 ; s_d = 1 ;
#200;
s_a = 0 ; s_b = 1 ; s_c = 1 ; s_d = 0 ;
#200;
s_a = 0 ; s_b = 1 ; s_c = 1 ; s_d = 1 ;
#200;
s_a = 1 ; s_b = 0 ; s_c = 0 ; s_d = 0 ;
#200;
s_a = 1 ; s_b = 0 ; s_c = 0 ; s_d = 1 ;
#200;
s_a = 1 ; s_b = 0 ; s_c = 1 ; s_d = 0 ;
#200;
s_a = 1 ; s_b = 0 ; s_c = 1 ; s_d = 1 ;
#200;
s_a = 1 ; s_b = 1 ; s_c = 0 ; s_d = 0 ;
#200;
s_a = 1 ; s_b = 1 ; s_c = 0 ; s_d = 1 ;
#200;
s_a = 1 ; s_b = 1 ; s_c = 1 ; s_d = 0 ;
#200;
s_a = 1 ; s_b = 1 ; s_c = 1 ; s_d = 1 ;
#200;
end
endmodule
例子4.功能设计:1S闪烁,500ms亮500ms灭
// Create Date: 2024/03/13 16:06:55
// Design Name: hilary
// Module Name: led_flash
module led_flash(
Clk,
Reset_n,
Led
);
input Clk;
input Reset_n;
output Led;
reg [24:0] counter ;
reg Led ;
//<=表示非阻塞赋值
always@(posedge Clk or negedge Reset_n )
if (!Reset_n)//处于复位u状态
counter <= 0 ;
else if(counter == 25000000-1)//工作状态
counter<=0 ;
else
counter <= counter + 1'd1 ;
always@(posedge Clk or negedge Reset_n )
if (!Reset_n)//处于复位u状态
Led <= 0 ;
else if(counter == 25000000-1)//工作状态
Led <= !Led ;
endmodule
测试:
`timescale 1ns / 1ns
// Create Date: 2024/03/13 16:36:04
// Design Name: hilary
// Module Name: led_flash_tb
module led_flash_tb ;
reg Clk;
reg Reset_n;
wire Led;
led_flash led_flash(
.Clk(Clk),
.Reset_n(Reset_n),
.Led(Led)
);
initial Clk = 1 ;
always #10 Clk = !Clk ;
initial begin
Reset_n = 0 ;
#201 ;
Reset_n = 1 ;
#2000000000 ;
$stop ;
end
endmodule
例子5:跑马灯1(普通实现):
// Create Date: 2024/03/13 19:46:36
// Design Name: hilary
// Module Name: led_run
module led_run(
Clk,
Reset_n,
Led
);
input Clk;
input Reset_n;
output reg [7:0] Led;
reg [24:0] counter ;
//计时器
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0 ;
else if(counter == 25000000 - 1)
counter <= 0 ;
else
counter <= counter + 1 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Led <= 8 'b0000_0001;
else if(counter == 25 'd24999999)begin
if(Led ==8 'b1000_0000)
Led <= 8 'b0000_0001 ;
else
Led <= Led << 1 ;
end
else
Led <= Led ;
endmodule
测试代码:
`timescale 1ns / 1ns
// Create Date: 2024/03/13 20:10:42
// Design Name: hilary
// Module Name: led_run_tb
module led_run_tb;
reg Clk ;
reg Reset_n ;
wire [7:0] Led ;
led_run led_run(
.Clk(Clk),
.Reset_n(Reset_n),
.Led(Led)
);
initial Clk = 1;
always #10 Clk = ~Clk ;
initial begin
Reset_n = 0 ;
#201;
Reset_n = 1;
#4000000000;
$stop;
end
endmodule
例子6:跑马灯(拼接实现)
// Create Date: 2024/03/13 19:46:36
// Design Name: hilary
// Module Name: led_run
module led_run1(
Clk,
Reset_n,
Led
);
input Clk;
input Reset_n;
output reg [7:0] Led;
reg [24:0] counter ;
//计时器
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0 ;
else if(counter == 250000 - 1)
counter <= 0 ;
else
counter <= counter + 1 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Led <= 8 'b0000_0001;
else if(counter == 25 'd249999)begin
if(Led ==8 'b1000_0000)
Led <= 8 'b0000_0001 ;
else
Led <= {Led[6:0],Led[7]} ;
end
else
Led <= Led ;
endmodule
测试代码同上
例子7:跑马灯(3-8译码器实现)
// Create Date: 2024/03/13 19:46:36
// Design Name: hilary
// Module Name: led_run
module led_run3(
Clk,
Reset_n,
Led
);
input Clk;
input Reset_n;
output [7:0] Led;
reg [24:0] counter ;
//计时器
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0 ;
else if(counter == 25 'd24999)
counter <= 0 ;
else
counter <= counter + 1 ;
reg [2:0] counter2 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter2 <= 0 ;
else if(counter == 25 'd24999)
counter2 <= counter2 +1 'b1 ;
decoder_3_8 decoder_3_8(
. a(counter2[2]),
. b(counter2[1]),
. c(counter2[0]),
. out(Led)
);
endmodule
效果展示:
关于parameter参数传递的语法:
// Create Date: 2024/03/19 14:17:03
// Design Name: hilary
// Module Name: led_run8_test
module led_run8_test(
Clk,
Reset_n,
Led
);
input Clk;
input Reset_n;
output [3:0] Led;
led_run8 led_run8_inst0(
.Clk(Clk),
.Reset_n(Reset_n),
.Led(Led[0])
);
defparam led_run8_inst0.MCNT = 2499999 ;
led_run8 led_run8_inst1(
.Clk(Clk),
.Reset_n(Reset_n),
.Led(Led[1])
);
defparam led_run8_inst1.MCNT = 4999999 ;
led_run8 led_run8_inst2(
.Clk(Clk),
.Reset_n(Reset_n),
.Led(Led[2])
);
defparam led_run8_inst2.MCNT = 7499999 ;
led_run8 led_run8_inst3(
.Clk(Clk),
.Reset_n(Reset_n),
.Led(Led[3])
);
defparam led_run8_inst3.MCNT = 999999 ;
endmodule
说明:调用之前写的led_run8例程。
例子8:
// Create Date: 2024/03/19 15:25:33
// Design Name: hilary
// Module Name: counter_led_0
//功能:LED灯亮0.5秒,灭0.5秒的状态循环
module counter_led_1(
Clk,
Reset_n,
Led
);
input Clk;
input Reset_n;
output reg Led;
reg [25:0] counter;
parameter MCNT = 50000000 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0 ;
else if(counter == MCNT - 1 )
counter <= 0 ;
else
counter <= counter + 1 'b1 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Led <= 0 ;
else if(counter == MCNT/2 - 1)
Led <= 1;
else if(counter == MCNT - 1)
Led <= 0 ;
endmodule
仿真:
`timescale 1ns / 1ns
// Create Date: 2024/03/13 16:36:04
// Design Name: hilary
// Module Name: led_flash_tb
module counter_led_tb ;
reg Clk;
reg Reset_n;
wire Led;
counter_led_1
#(
.MCNT(125000)
)
counter_led_1(
.Clk(Clk),
.Reset_n(Reset_n),
.Led(Led)
);
initial Clk = 1 ;
always #10 Clk = !Clk ;
initial begin
Reset_n = 0 ;
#201 ;
Reset_n = 1 ;
#200000000 ;
$stop ;
end
endmodule
例子9:
// Create Date: 2024/03/19 15:25:33
// Design Name: hilary
// Module Name: counter_led_0
//功能:让LED灯亮0.25秒,灭0.75秒
module counter_led_2(
Clk,
Reset_n,
Led
);
input Clk;
input Reset_n;
output reg Led;
reg [25:0] counter;
parameter MCNT = 50000000 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0 ;
else if(counter == MCNT - 1 )
counter <= 0 ;
else
counter <= counter + 1 'b1 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Led <= 0 ;
else if(counter == MCNT/2 + MCNT/4 - 1)
Led <= 1;
else if(counter == MCNT - 1)
Led <= 0 ;
endmodule
仿真:
`timescale 1ns / 1ns
// Create Date: 2024/03/13 16:36:04
// Design Name: hilary
// Module Name: led_flash_tb
module counter_led_tb ;
reg Clk;
reg Reset_n;
wire Led;
counter_led_2
#(
.MCNT(125000)
)
counter_led_2(
.Clk(Clk),
.Reset_n(Reset_n),
.Led(Led)
);
initial Clk = 1 ;
always #10 Clk = !Clk ;
initial begin
Reset_n = 0 ;
#201 ;
Reset_n = 1 ;
#200000000 ;
$stop ;
end
endmodule
例子10:
// Create Date: 2024/03/19 15:25:33
// Design Name: hilary
// Module Name: counter_led_0
//功能:让LED亮0.25秒,灭0.5秒,亮0.75秒,灭1秒的状态循环
module counter_led_3(
Clk,
Reset_n,
Led
);
input Clk;
input Reset_n;
output reg Led;
reg [26:0] counter;
parameter MCNT = 125000000 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0 ;
else if(counter == MCNT - 1 )
counter <= 0 ;
else
counter <= counter + 1 'b1 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Led <= 1 ;
else if(counter == MCNT/10 - 1)
Led <= 0;
else if(counter == MCNT/10 + MCNT/5 - 1)
Led <= 1 ;
else if(counter == (MCNT/10 + MCNT/5)*2 - 1)
Led <= 0 ;
else if(counter == MCNT - 1)
Led <= 1;
endmodule
仿真:
`timescale 1ns / 1ns
// Create Date: 2024/03/13 16:36:04
// Design Name: hilary
// Module Name: led_flash_tb
module counter_led_tb ;
reg Clk;
reg Reset_n;
wire Led;
counter_led_3
#(
.MCNT(125000)
)
counter_led_3(
.Clk(Clk),
.Reset_n(Reset_n),
.Led(Led)
);
initial Clk = 1 ;
always #10 Clk = !Clk ;
initial begin
Reset_n = 0 ;
#201 ;
Reset_n = 1 ;
#200000000 ;
$stop ;
end
endmodule
例子11:
// Create Date: 2024/03/22 15:25:33
// Design Name: hilary
// Module Name: counter_led_0
//功能:让LED灯以指定的亮灭模式亮灭,亮灭模式未知,由用户指定模式,
//以0.25为一个变化周期,8个变化状态为一个循环
module counter_led_4(
Clk,
Reset_n,
Ctrl,
Led
);
input Clk;
input Reset_n;
input [7:0] Ctrl;
output reg Led;
reg [26:0] counter;
parameter MCNT = 100000000 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0 ;
else if(counter == MCNT - 1 )
counter <= 0 ;
else
counter <= counter + 1 'b1 ;
// always@(posedge Clk or negedge Reset_n)
// if(!Reset_n)
// Led <= 0 ;
// else if(counter == MCNT/10 - 1)
// Led <= Ctrl[0];
// else if(counter == MCNT*2/8 - 1)
// Led <= Ctrl[1] ;
// else if(counter == MCNT*3/8 - 1)
// Led <= Ctrl[2] ;
// else if(counter == MCNT*4/8 - 1)
// Led <= Ctrl[3] ;
// else if(counter == MCNT*5/8 - 1)
// Led <= Ctrl[4] ;
// else if(counter == MCNT*6/8 - 1)
// Led <= Ctrl[5] ;
// else if(counter == MCNT*2/8 - 1)
// Led <= Ctrl[6] ;
// else if(counter == MCNT*7/8 - 1)
// Led <= Ctrl[7] ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Led <= 0 ;
else case(counter)
MCNT*1/8 -1 : Led <= Ctrl[0];
MCNT*2/8 -1 : Led <= Ctrl[1];
MCNT*3/8 -1 : Led <= Ctrl[2];
MCNT*4/8 -1 : Led <= Ctrl[3];
MCNT*5/8 -1 : Led <= Ctrl[4];
MCNT*1/8 -1 : Led <= Ctrl[5];
MCNT*1/8 -1 : Led <= Ctrl[6];
MCNT*1/8 -1 : Led <= Ctrl[7];
default : Led <= Led;
endcase
endmodule
仿真:
`timescale 1ns / 1ns
// Create Date: 2024/03/13 16:36:04
// Design Name: hilary
// Module Name: led_flash_tb
module counter_led_4_tb ;
reg Clk;
reg Reset_n;
reg [7:0] Ctrl;
wire Led;
counter_led_4
#(
.MCNT(100000)
)
counter_led_4(
.Clk(Clk),
.Reset_n(Reset_n),
.Ctrl(Ctrl),
.Led(Led)
);
initial Clk = 1 ;
always #10 Clk = !Clk ;
initial begin
Reset_n = 0 ;
Ctrl = 0 ;
#201 ;
Reset_n = 1 ;
Ctrl = 8 'b1000_0110 ;
#200000000 ;
$stop ;
end
endmodule
例子12:
// Create Date: 2024/03/22 15:25:33
// Design Name: hilary
// Module Name: counter_led_0
//功能:让LED灯以指定的亮灭模式亮灭,亮灭模式未知,由用户指定模式,
//8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择。
module counter_led_5(
Clk,
Reset_n,
Ctrl,
Time,
Led
);
input Clk;
input Reset_n;
input [7:0] Ctrl;
input [31:0] Time;
output reg Led;
reg [31:0] counter;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0 ;
else if(counter == Time - 1 )
counter <= 0 ;
else
counter <= counter + 1 'b1 ;
reg [2:0] counter2 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter2 <= 0 ;
else if(counter == Time - 1 )
counter2 <= counter2 +1 'b1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Led <= 0 ;
else case(counter2)
0 : Led <= Ctrl[0];
1 : Led <= Ctrl[1];
2 : Led <= Ctrl[2];
3 : Led <= Ctrl[3];
4 : Led <= Ctrl[4];
5 : Led <= Ctrl[5];
6 : Led <= Ctrl[6];
7 : Led <= Ctrl[7];
default : Led <= Led;
endcase
endmodule
仿真:
`timescale 1ns / 1ns
// Create Date: 2024/03/13 16:36:04
// Design Name: hilary
// Module Name: led_flash_tb
module counter_led_5_tb ;
reg Clk;
reg Reset_n;
reg [7:0] Ctrl;
reg [31:0]Time;
wire Led;
counter_led_5
#(
.MCNT(100000)
)
counter_led_5(
.Clk(Clk),
.Reset_n(Reset_n),
.Ctrl(Ctrl),
.Time(Time),
.Led(Led)
);
initial Clk = 1 ;
always #10 Clk = !Clk ;
initial begin
Reset_n = 0 ;
Ctrl = 0 ;
#201 ;
Reset_n = 1 ;
Time = 2500 ;
Ctrl = 8 'b1000_0110 ;
#200000000 ;
$stop ;
end
endmodule
可控的线性序列机:
// Create Date: 2024/03/22 15:25:33
// Design Name: hilary
// Module Name: counter_led_0
//功能:每隔10ms,让LED灯的一个8状态循环一次,每个状态的变化的时间制值小一点方便测试,比如10us
module counter_led_7(
Clk,
Reset_n,
Ctrl,
Time,
Led
);
input Clk;
input Reset_n;
input [7:0] Ctrl;
input [31:0] Time;
output reg Led;
reg [31:0] counter;
reg EN ;
reg [18:0] counter0 ;
//10ms周期定时器
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter0 <= 0 ;
else if(counter0 == 500000 - 1 )
counter0 <= 0 ;
else
counter0 <= counter0 + 1 'b1 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
EN <= 0 ;
else if (counter0 == 0)
EN <= 1 ;
else if( (counter2 == 7) && (counter == Time -1) )
EN <= 0 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0 ;
else if(EN)begin
if(counter == Time -1 )
counter <= 0 ;
else
counter <= counter + 1 'b1 ;
end
else
counter <= 0 ;
reg [2:0] counter2 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter2 <= 0 ;
else if(EN)begin
if(counter == Time - 1 )
counter2 <= counter2 +1 'b1;
end
else
counter2 <= 0 ;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Led <= 0 ;
else case(counter2)
0 : Led <= Ctrl[0];
1 : Led <= Ctrl[1];
2 : Led <= Ctrl[2];
3 : Led <= Ctrl[3];
4 : Led <= Ctrl[4];
5 : Led <= Ctrl[5];
6 : Led <= Ctrl[6];
7 : Led <= Ctrl[7];
default : Led <= Led;
endcase
endmodule