概述
补充组合逻辑电路实现:全加器
原理图:
使用两个半加器组成全加器,第一个半加器的输入in_1、in_2作为全加器的输入,同时in_1作为第二个半加器的输入;
第二个半加器的输入2作为全加器的进位cin;
将半加器1与半加器2的进位输出用或门连接作为全加器的进位输出,半加器2的求和输出作为全加器的求和输出。
verilog代码实现功能:
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
仿真逻辑文件:
`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代码:
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
上述采用异步清零的方式实现功能。若采用同步清零,代码应为:
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
仿真逻辑代码:
`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代码实现:
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代码实现仿真
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
仿真代码:
`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学习笔记:verilog基础代码与modelsim仿真(二)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复