[Synth 8-327] inferring latch for variable 'led_breath_reg' ["C:/Users/warrior/Desktop/ZYNQ/pl/key_breath/rtl/led_breath.v":66]
因为在组合逻辑中,用了非阻塞赋值的方式赋值信号。
组合逻辑自己给自己赋值会产生组合回环,输出不稳定。
模块框图:
代码:
/*
电容按键的上升沿检测,拉高一个时钟周期作为控制标志信号。
*/
module key(
input wire sys_clk ,
input wire sys_rst_n ,
input wire key_cup ,
output reg key_flag
);
// reg signal define
reg key_cup_r1 ;
reg key_cup_r2 ;
wire key_flag_r ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
key_cup_r1 <= 1'b0 ;
key_cup_r2 <= 1'b0 ;
end
else begin
key_cup_r1 <= key_cup ;
key_cup_r2 <= key_cup_r1 ;
end
end
assign key_flag_r = key_cup_r1 && ~key_cup_r2 ;
// output key_flag
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
key_flag <= 1'b0 ;
else
key_flag <= key_flag_r ;
end
endmodule
// 呼吸灯,控制信号来一次,切换灯呼吸。
module led_breath(
input wire sys_clk ,
input wire sys_rst_n ,
input wire key_flag ,
output reg [1:0] led_out
);
parameter MAX_CNT_MS = 1000 ,
MAX_CNT_US = 1000 ,
MAX_CNT_NS = 50 ;
// reg signal define
reg [5:0] cnt_ns ;
reg [9:0] cnt_us ;
reg [9:0] cnt_ms ;
reg led_mod;
reg led_sel;
//reg led_breath ;
wire led_breath ;
/*************************************************************/
// reg [5:0] cnt_ns ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_ns <= 6'd0 ;
else if((cnt_ns == MAX_CNT_NS - 1) || (key_flag))
cnt_ns <= 6'd0 ;
else
cnt_ns <= cnt_ns + 1'b1 ;
end
// reg [9:0] cnt_us ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_us <= 10'd0 ;
else if(((cnt_us == MAX_CNT_US - 1)&&(cnt_ns == MAX_CNT_NS - 1))||(key_flag))
cnt_us <= 10'd0 ;
else if(cnt_ns == MAX_CNT_NS - 1)
cnt_us <= cnt_us + 1'b1 ;
else
cnt_us <= cnt_us ;
end
// reg [9:0] cnt_ms ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_ms <= 10'd0 ;
else if(((cnt_ms == MAX_CNT_MS - 1)&&(cnt_us == MAX_CNT_US - 1)&&(cnt_ns == MAX_CNT_NS - 1))||(key_flag))
cnt_ms <= 10'd0 ;
else if((cnt_us == MAX_CNT_US - 1)&&(cnt_ns == MAX_CNT_NS - 1))
cnt_ms <= cnt_ms + 1'b1 ;
else
cnt_ms <= cnt_ms ;
end
// reg led_mod ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
led_mod <= 1'b1 ;
else if(key_flag)
led_mod <= 1'b1 ;
else if((cnt_ms == MAX_CNT_MS - 1)&&(cnt_us == MAX_CNT_US - 1)&&(cnt_ns == MAX_CNT_NS - 1))
led_mod <= ~led_mod ;
else
led_mod <= led_mod ;
end
// led_breath
// always @(posedge sys_clk or negedge sys_rst_n) begin
// if(~sys_rst_n)
// led_breath <= 1'b0 ;
// else if((led_mod && (cnt_ms > cnt_us)) || (~led_mod && (cnt_ms < cnt_us)))
// led_breath <= 1'b1 ;
// else if(((led_mod) && (cnt_ms <= cnt_us)) || (~led_mod && (cnt_ms >= cnt_us)))
// led_breath <= 1'b0 ;
// else
// led_breath <= led_breath ;
// end
// always @(*) begin
// if(~sys_rst_n)
// led_breath = 1'b0 ;
// else if((led_mod && (cnt_ms > cnt_us)) || (~led_mod && (cnt_ms < cnt_us)))
// led_breath = 1'b1 ;
// else if(((led_mod) && (cnt_ms <= cnt_us)) || (~led_mod && (cnt_ms >= cnt_us)))
// led_breath = 1'b0 ;
// else
// led_breath = led_breath ;
// end
assign led_breath = ((led_mod && (cnt_ms > cnt_us)) || (~led_mod && (cnt_ms < cnt_us))) ? 1'b1 : 1'b0 ;
// reg led_sel ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
led_sel <= 1'b0 ;
else if(key_flag)
led_sel <= ~led_sel ;
end
// output reg [1:0] led_out
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
led_out <= 2'b00 ;
else if(led_sel == 0)
led_out <= {1'b0,led_breath} ;
else if(led_sel == 1)
led_out <= {led_breath,1'b0} ;
else
led_out <= 2'b00 ;
end
endmodule
module top(
input wire sys_clk ,
input wire sys_rst_n ,
input wire key_cup ,
output wire [1:0] led_out
);
// wire signal define
wire key_flag ;
key key_inst(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.key_cup ( key_cup ) ,
.key_flag ( key_flag )
);
led_breath led_breath_inst(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.key_flag ( key_flag ) ,
.led_out ( led_out )
);
endmodule
`timescale 1ns/1ns
module test_top();
reg sys_clk ;
reg sys_rst_n ;
reg key_cup ;
wire [1:0] led_out ;
top top_inst(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.key_cup ( key_cup ) ,
.led_out ( led_out )
);
parameter CYCLE = 20 ;
defparam top_inst.led_breath_inst.MAX_CNT_MS = 100 ;
defparam top_inst.led_breath_inst.MAX_CNT_US = 100 ;
defparam top_inst.led_breath_inst.MAX_CNT_NS = 50 ;
initial begin
sys_clk = 1'b1 ;
sys_rst_n <= 1'b0 ;
key_cup <= 1'b0 ;
#( CYCLE * 2 ) ;
sys_rst_n <= 1'b1 ;
#(CYCLE * 10) ;
#(CYCLE * 1200000);
key_cup <= 1'b1;
#(CYCLE * 10) ;
key_cup <= 1'b0 ;
#(CYCLE * 1200000);
$stop ;
end
always #(CYCLE / 2) sys_clk = ~sys_clk;
endmodule
仿真:
忘记截图了