【原创】从零开始学习FPGA-----复杂计数器练习
1赞【原创】从零开始学习FPGA-----复杂计数器练习
1. 复杂计数器练习
1) 模块时钟是100M。dout的依次如下变化:
a 第一阶段时间是20us。此时如果din_vld出现超过50ns的高电平脉冲,则dout输出10ns的高电平;
b 第二阶段时间是40us。此时如果din_vld出现超过100ns的高电平脉冲,则dout输出10ns的高电平;
c 第三阶段时间是100us。此时如果din_vld出现超过200ns的高电平脉冲,则dout输出10ns的高电平;
d 第四阶段时间是200us。此时如果din_vld出现超过40ns的高电平脉冲,则dout输出10ns的高电平;
e 循环a~d。
分析如下:
这道练习题需要3个计数器,计数器0,计din_vld阶段50ns 100ns 200ns 40ns的产生,计数器1计20us 40us 100us 200us,计数器2计a,b,c,d这4个阶段。
不多说,代码如下,经过这几天的训练,在代码规范性上有了很大提升,值得鼓励。。
`timescale 1ns/1ns
module module_name(
clk ,
rst_n ,
din_vld,
//其他信号,举例dout
dout
);
//参数定义
parameter DATA_W = 1;
//输入信号定义
input clk ;//10ns
input rst_n ;
input din_vld;
//输出信号定义
output[DATA_W-1:0] dout ;
//输出信号reg定义
reg [DATA_W-1:0] dout ;
//参数定义
parameter T_20US = 15'd2_000;
parameter T_40US = 15'd4_000;
parameter T_100US = 15'd10_000;
parameter T_200US = 15'd20_000;
parameter T_50NS = 5'd5;
parameter T_100NS = 5'd10;
parameter T_200NS = 5'd20;
parameter T_40NS = 5'd4;
reg[5:0] cnt0;//计50ns 100ns 200ns 40ns
reg[14:0] cnt1;//计20us 40us 100us 200us
reg[3:0] cnt2;//计 a b c d
//各阶段中间变量
reg[5:0] t_ns ;
reg[14:0] t_us ;
//计数器0
assign add_cnt0 = din_vld ;
assign end_cnt0 = ~din_vld ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cnt0 <= 0;
end
else if(add_cnt0)begin
if(end_cnt0)begin
cnt0 <= 0;
end
else if(cnt0 == t_ns)begin
cnt0 <= cnt0;
end
else begin
cnt0 <= cnt0 + 1;
end
end
end
//计数器1
assign end_cnt1 = (cnt2 == t_us-1) && add_cnt1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cnt1 <= 0;
end
else if(end_cnt1)
cnt1 <= 0;
else
cnt1 <= cnt1 +1;
end
//计数器2
assign add_cnt2 = end_cnt1;
assign end_cnt2 = (cnt2 == 4-1) && add_cnt2;
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cnt2 <= 0;
end
else if(add_cnt2)begin
if(end_cnt2)
cnt2 <= 0;
else
cnt2 <= cnt2 +1;
end
end
//中间变量
always @(*)begin
if(cnt2==0)begin
t_ns = T_50NS;
t_us = T_20US;
end
else if(cnt2 == 1)begin
t_ns = T_100NS;
t_us = T_40US;
end
else if(cnt2 == 2)begin
t_ns = T_200NS;
t_us = T_100US;
end
else begin
t_ns = T_40NS;
t_us = T_200US;
end
end
//输出dout
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout <= 1'b0;
end
else if(cnt0 == t_ns-1 && din_vld) begin
dout <= 1'b1;
end
else begin
dout <= dout;
end
end
endmodule
计数器练习到这已经练的差不多了,接下来要进行串口,SPI,VGA,FIFO等模块的学习,这些模块计数器是基础,基础一定要打好,对以后的学习会起到事半功倍的效果。
今天就到这里,睡觉了,晚安,同学们。