【FPGA/verilog -入门学习3】verilog脉冲计数
2023-12-14 18:22:45
需求:
1,在EN为高电平时,对输入的Pluse 脉冲计数,每个上升沿计数一次
2,EN 为低电平时,输出计数值和计数完成状态
需求分析:
输入输出
输入:clk,rest_n,i_en,pluse
输出:o_cnt ,o_state
操作步骤
输入端推进:
步骤1,对pluse 进行脉冲边沿检测,识别出每次上升沿,用于后续的计数
输出端获取:
步骤2,对输出o_state 实现方式:在每一次en=0 时识别为计数结束。可以用脉冲边沿检测法,检测en信号的下降沿作为o_state 的结束信号
步骤3:使用内部寄存器r_cnt ,当en=1时,pluse 的上升沿脉冲计数。计数到en= 0 时清零。
步骤4:当en = 0时,且r_cnt 有数值,将o_cnt <=r_cnt.
vlg_design
/
/*
脉冲计数,当是能时,对pluse脉冲计数
实现步骤
1)产生pluse 上升沿脉冲 一个clk时钟
2)产生i_en 下降沿,当下降沿 o_state=1
3)对pluse上升沿计数,锁存在r_cnt
4)当o_state=1 时,o_cnt<=r_cnt
*/
/
`timescale 1ns/1ps
module vlg_design(
input clk,//100M
input pulse,//
input rest_n,
input i_en,
output reg[31:0] o_cnt, //输出计数值
output o_state
);
reg [1:0] r_pluse;
reg [1:0] r_en;
wire w_pluse_pos;
wire w_en_neg;
reg[31:0] r_cnt;
//产生一个pluse 上升沿脉冲时钟
always @(posedge clk) begin
if(!rest_n) r_pluse <='b00;
else r_pluse <= {r_pluse[0],pulse};
end
assign w_pluse_pos = r_pluse[0] & ~r_pluse[1];
//产生一个i_en 下降沿脉冲时钟
//en 下降沿时 o_state =1
always @(posedge clk) begin
if(!rest_n) r_en <='b00;
else r_en <= {r_en[0],i_en};
end
assign o_state = r_en[1] & ~r_en[0];
//EN = 1时候计数
always @(posedge clk) begin
if(!rest_n) r_cnt <= 'b0;
else if(i_en)
if(w_pluse_pos)r_cnt <= r_cnt + 1'b1;
else ;
else r_cnt <= 'b0;
end
//输出o_cnt
always @(posedge clk) begin
if(!rest_n) o_cnt <= 'b0;
else if(!i_en && r_cnt) begin
o_cnt <= r_cnt;
$display("r_cnt=%d\n",r_cnt);//显示
end
else o_cnt <= 'b0;
end
endmodule
testbench_top
`timescale 1ns/1ps
module testbench_top();
//参数定义
`define CLK_PERIORD 10 //时钟周期设置为10ns(100MHz)
//接口申明
reg clk;
reg pulse;
reg rest_n;
reg i_en;
wire [31:0] o_cnt;
wire o_state;
vlg_design uut_vlg_design(
.clk(clk),
.pulse(pulse),
.rest_n(rest_n),
.i_en(i_en),
.o_cnt(o_cnt),
.o_state(o_state)
);
//时钟和复位初始化、复位产生
initial begin
clk <= 0;
rest_n <= 0;
#10;
rest_n <= 1;
clk <= 1;
pulse <= 1'b0;
i_en <= 0;
end
//时钟产生
always #(`CLK_PERIORD/2) clk = ~clk;
integer i;
//测试激励产生
initial begin
@(posedge rest_n); //等待复位完成
@(posedge clk);
i_en <= 1;
@(posedge clk);
for (i = 0; i < 16; i = i+1) begin
pulse = ~pulse;
repeat(3)@(posedge clk);
end
i_en <= 0;
@(posedge clk);
i_en <= 0;
for (i = 0; i < 16; i = i+1) begin
pulse = ~pulse;
repeat(3)@(posedge clk);
end
i_en <= 0;
@(posedge clk);
i_en <= 1;
@(posedge clk);
for (i = 0; i < 6; i = i+1) begin
pulse = ~pulse;
repeat(5)@(posedge clk);
end
i_en <= 0;
@(posedge clk);
#2_000_000;
$stop;
end
endmodule
仿真结果
难点分析
1,按模块划分,
//产生一个pluse 上升沿脉冲时钟
//产生一个i_en 下降沿脉冲时钟 //en 下降沿时 o_state =1
//EN = 1时候计数
//输出o_cnt
各模块的赋值部分,相互独立,各自处理各自判断,防止时序偏差
文章来源:https://blog.csdn.net/cengqiu4314/article/details/134873297
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!