在FPGA程序编写中,通常会遇到两种电路:组合逻辑电路以及时序逻辑电路。其中时序逻辑电路最为重要。
“重要的逻辑时序是设计出来的,不是凑出来的”,这不是一句空话,而是要求我们时时刻刻记心中的。
在保证一个always模块里只输出一个信号的基础上,按照复位条件,初始条件,结束条件,触发条件,拉高触发条件,拉低触发条件进行编写。
类型一:计数器常用架构1
always@(时钟和复位) begin
if(复位条件) begin
//执行复位
end
else if(触发条件) begin
if(结束条件) begin
//执行结束事件
end
else begin
//执行触发事件
end
end
else begin
//执行保持事件
end
end
//demo
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin //执行复位条件
cnt<=0;
end
else if(en==1)begin //执行en=1条件
if(cnt == 10-1) begin //执行cnt==10-1条件
cnt<=0; //计数结束后清零,循环计数
//cnt<=cnt; //计数结束后保持,单次计数
end
else begin
cnt<=cnt+1;
end
end
else begin
cnt<=cnt; //保持cnt的值
end
end
类型二:计数器常用架构2
always@(时钟和复位) begin
if(复位条件) begin
//执行复位
end
else if(触发条件) begin
if(不结束条件) begin
//执行触发事件
end
else begin
//执行保持事件
end
end
end
//demo
always@(posedge clk or negedge rst_n) begin
if(rst_n==1'b0) begin
cnt<=0;
end
else if(en==1) begin
if(cnt<10-1) begin
cnt<=cnt+1;
end
else begin
cnt<=0; //计数结束后清零,循环计数
//cnt<=cnt; //计数结束后保持,单次计数
end
end
end
类型三:计数器常用架构3,结束条件和触发条件互斥
always@(时钟和复位) begin
if(复位条件) begin
//执行复位事件
end
else if(结束条件) begin
//执行结束事件
end
else if(触发条件) begin
//执行触发事件
end
else begin
//执行保持事件
end
end
//demo
always@(posedge clk or negedge rst_n) begin
if(rst_n==1'b0) begin
cnt<=0;
end
else if(cnt==10-1) begin
cnt <=0; //计数结束后清零,循环计数
//cnt<=cnt; //计数结束后保持,单次计数
end
else if(en==1) begin
cnt<=cnt+1;
end
else begin
cnt<=cnt;
end
end
类型四:计数器常用架构4,当结束条件优先级较高时建议用
always@(时钟和复位) begin
if(复位条件||结束条件) begin
//执行复位
end
else if(触发条件) begin
//执行触发事件
end
else begin
//执行保持事件
end
end
//demo
always@(posedge clk or negedge rst_n) begin
if(rst_n==1'b0|| cnt==10-1) begin
cnt<=0;
end
else if(en==1) begin
cnt<=cnt+1;
end
else begin
cnt<=cnt;
end
end
类型五:不建议用!!!容易造成多重赋值,但是会被系统优化掉
always@(时钟和复位) begin
if(复位条件) begin
//执行复位
end
else if(触发条件) begin
//执行触发事件
if(结束条件) begin
//执行结束事件
end
end
else begin
//执行保持事件
end
end
//demo
always@(posedge clk or negedge rst_n) begin
if(rst_n==1'b0) begin
cnt<=0; //执行复位条件
end
else if(en==1) begin
cnt<=cnt+1;//执行触发事件
if(cnt==10-1) begin
cnt <=0; //计数结束后清零,循环计数
// cnt<=cnt; //计数结束后保持,单次计数
end
end
else begin
cnt<=cnt;//执行保持事件
end
end
类型六:常用于控制信号时序
always@(时钟和复位) begin
if(复位条件) begin
//执行复位
end
else if(拉高触发条件) begin
//执行拉高操作
else if(拉低触发条件) begin
//执行拉低操作
else begin
//执行保持事件
end
end
//demo
always@(posedge clk or negedge rst_n) begin
if(rst_n==1'b0) begin
ctrl_sig<=0;//执行复位
end
else if(trigger_high) begin
ctrl_sig<=1; //执行拉高操作
end
else if(trigger_low) begin
ctrl_sig<=0; //执行拉低操作
end
else begin
ctrl_sig<=ctrl_sig;//执行保持事件
end
end