我是靠谱客的博主 勤恳楼房,这篇文章主要介绍FPGA学习笔记:verilog基础代码与modelsim仿真(二),现在分享给大家,希望可以做个参考。

补充组合逻辑电路实现:全加器

原理图:

在这里插入图片描述

使用两个半加器组成全加器,第一个半加器的输入in_1、in_2作为全加器的输入,同时in_1作为第二个半加器的输入;

第二个半加器的输入2作为全加器的进位cin;

将半加器1与半加器2的进位输出用或门连接作为全加器的进位输出,半加器2的求和输出作为全加器的求和输出。



verilog代码实现功能:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
module full_adder( input wire in_1, input wire in_2, input wire cin, output wire sum, output wire count ); wire h0_sum; wire h0_count; wire h1_count; half_adder half_adder_inst0 ( .in_1 (in_1 ) , .in_2 (in_2 ) , .sum (h0_sum) , .count (h0_count) ); half_adder half_adder_inst1 ( .in_1 ( cin) , .in_2 ( h0_sum) , .sum (sum) , .count ( h1_count) ); assign count = (h0_count | h1_count); endmodule

其中,需要用到半加器的功能实例化,半加器的代码具体参考上一篇文章: https://blog.csdn.net/qq_52899124/article/details/128219813



仿真逻辑文件:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
`timescale 1ns/1ns module tb_full_adder(); reg in_1; reg in_2; reg cin; wire sum; wire count; initial begin in_1 <= 1'b0; in_2 <= 1'b0; cin <= 1'b0; end initial begin $timeformat(-9,0,"ns",6); $monitor("@time %t :in_1=%b,in_2=%b,cin=%b,sum=%b,count=%b" ,$time,in_1,in_2,cin,sum,count); end always #10 in_1 <= {$random} % 2; always #10 in_2 <= {$random} % 2; always #10 cin <= {$random} % 2; full_adder full_adder_inst ( .in_1(in_1) , .in_2(in_2) , .cin (cin ) , .sum (sum ) , .count(count) ); endmodule


modelsim仿真波形图:

在这里插入图片描述










时序逻辑电路

D触发器:

波形图及原理图:

在这里插入图片描述

verilog代码:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
module flip_flop( input wire sys_clk , //50Mhz input wire sys_rst_n , input wire key_in , output reg led_out ); //Asynchronous reset always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) led_out <= 1'b0; else led_out <= key_in; endmodule

上述采用异步清零的方式实现功能。若采用同步清零,代码应为:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module flip_flop( input wire sys_clk , //50Mhz input wire sys_rst_n , input wire key_in , output reg led_out ); //Synchronous reset always@(posedge sys_clk ) if(sys_rst_n == 1'b0) led_out <= 1'b0; else led_out <= key_in; endmodule


仿真逻辑代码:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
`timescale 1ns/1ns module tb_flip_flop(); reg sys_clk; reg sys_rst_n; reg key_in; wire led_out; initial begin sys_clk = 1'b1; sys_rst_n <= 1'b0; key_in <= 1'b0; #20 //delay 20ns sys_rst_n <= 1'b1; #210 sys_rst_n <= 1'b0; sys_rst_n <= 1'b1; end always #10 sys_clk =~sys_clk; always #20 key_in <= {$random} % 2; //input signal period should be greater than or equal to the clock period initial begin $timeformat(-9,0,"ns",6); $monitor("@time %t :key_in=%b,led_out=%b" ,$time,key_in,led_out); end flip_flop flip_flop_inst ( .sys_clk(sys_clk) , .key_in(key_in) , .sys_rst_n (sys_rst_n) , .led_out (led_out) ); endmodule


modelsim仿真波形图:

在这里插入图片描述






模M计数器——实现led灯闪烁

值得一提,模M的计算方式:
M = t / T M = t / T M=t/T
M:计数器模值 t:自定义时间周期 T:时钟周期(时钟频率的倒数)

波形图及原理图:

在这里插入图片描述

在这里插入图片描述

上述波形使用计数器全模值完成LED灯闪烁,耗费资源过多,可使用计数器一半模值使保持LED亮或灭,计数器计数达到一半模值后跳转到由0重新开始计数且LED灯状态取反即可实现。



verilog代码实现:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
module counter #( parameter CNT_MAX = 25'd24_999_999 ) ( input wire sys_clk , input wire sys_rst_n , output reg led_out ); reg [24:0] cnt; reg cnt_flag; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) cnt <= 25'd0; else if(cnt == CNT_MAX) cnt <= 25'd0; else cnt <= cnt + 25'd1; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) cnt_flag <= 1'b0; else if(cnt == (CNT_MAX-25'd1)) cnt_flag <= 1'b1; else cnt_flag <= 1'b0; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) led_out <= 1'b0; else if(cnt == CNT_MAX) led_out <= ~led_out; else led_out<= led_out; endmodule


方法2 使用cnt_flag作为中间变量

波形图:

在这里插入图片描述

当计数器达到模值一半时,cnt_flag获得一个高脉冲,当cnt_flag取高脉冲时,leg_out状态曲反;

verilog代码实现仿真

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
module counter #( parameter CNT_MAX = 25'd24_999_999 ) ( input wire sys_clk , input wire sys_rst_n , output reg led_out ); reg [24:0] cnt; reg cnt_flag; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) cnt <= 25'd0; else if(cnt == CNT_MAX) cnt <= 25'd0; else cnt <= cnt + 25'd1; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) cnt_flag <= 1'b0; else if(cnt == (CNT_MAX-25'd1)) cnt_flag <= 1'b1; else cnt_flag <= 1'b0; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) led_out<= 1'b0; else if(cnt_flag == 1'b1) led_out <= ~led_out; else led_out <= led_out; endmodule


仿真代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
`timescale 1ns/1ns module tb_counter(); reg sys_clk ; reg sys_rst_n ; wire led_out; initial begin sys_clk <= 1'b1; sys_rst_n<= 1'b0; #20 sys_rst_n <= 1'b1; end initial begin $timeformat(-9,0,"ns",6); $monitor("@time %t :sys_rst_n=%b,led_out=%b" ,$time,sys_rst_n,led_out); end always #10 sys_clk <= ~sys_clk; //50HZ counter #( .CNT_MAX(25'd24) //Pass of parameters )counter_inst ( .sys_clk(sys_clk) , .sys_rst_n(sys_rst_n) , .led_out(led_out) ); endmodule



方法一modelsim仿真波形图:

在这里插入图片描述

在这里插入图片描述






方法二modelsim仿真波形图:

在这里插入图片描述

在这里插入图片描述

最后

以上就是勤恳楼房最近收集整理的关于FPGA学习笔记:verilog基础代码与modelsim仿真(二)的全部内容,更多相关FPGA学习笔记内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部