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'd0;
else if(cnt_flag == 1'b1)
led_out <= ~led_out;
else
led_out <= led_out;
endmodule
首行代码为模块名,模块名要和文件夹名字相同,以免出错。小括号后面要带" ; ",模块里面定义输入输出变量
下面讲解wire和reg的区别与用法
1:wire型数据常用来表示以assign关键字指定的组合逻辑信号,模块的输入输出端口类型都默认为wire
型,wire
相当于物理连线,默认初始值是z
,reg型数据表示寄存器模型,用于always块、initial语句中被赋值的变量
2:wire使用在连续赋值语句中,reg用在过程赋值语句(always、initial)中
3:wire若无驱动器连接其值为z,reg默认初始值为不定值x
4:wire表示直通,即输入有变化,输出马上无条件地反映(如与、非门的简单连接)
reg表示一定要有触发,输出才会反映输入的状态。
5:wire一般用在组合逻辑中,reg一般用在时序逻辑中
6:reg变量在always中有两种情况:
1)always @(a or b or c)
形式的,即不带时钟边沿的,综合出来还是组合逻辑;
2)always @(posedge clk)
形式的,即带有边沿的,综合出来一般是时序逻辑,会包含触发器(Flip-Flop
)
7:always块不止能实现时序逻辑,还能实现组合逻辑:
(1)如果这个条件是时钟上升沿或下降沿,那硬件模型就是一个触发器,只有是指定了always@(posedge or negedge)才是触发器。
(2)如果这个条件是某一信号的高低电平,那这个硬件模型就是一个锁存器。
(3) 如果这个条件是赋值语句右侧任意操作数的变化,那这个硬件模型就是一个组合逻辑。
8:对组合逻辑输出变量,可以直接用assign。即如果不指定为reg类型,那么就默认为1位wire类型,故无需指定1位wire类型的变量。当然专门指定出wire类型,可能是多位或为使程序易读
9:reg
型数据保持最后一次的赋值,而wire
型数据需要持续的驱动
assign
中,表达式右侧的计算结果可以立即更新到表达式的左侧,可以理解为逻辑之后直接连接了一条线,这个逻辑对应于表达式的右侧,这条线对应于wire
;reg
型10:reg和wire类似于C、C++的变量,但若此变量要放在begin...end之内,则该变量只能是reg型;在begin...end之外,则用wire型;