请教:verilog中非阻塞赋值语句,多次赋值会怎样?

delacrxoix_xu 2012-03-11 06:57:02
例如这样, 我先给一个 timer 一直做加1操作,每个clk都是。下面有个判断,符合条件后,清零。请问这就赋值多次了,清零管用吗?

begin
autoNego_wait_timer <= autoNego_wait_timer + 1;
if(flp_cnt > 10)
begin
autoNego_wait_timer <= 0;
state_m_autoNego_rx <= STATE_NEGO_ALMOSTDONE;
end
else
begin
if(autoNego_wait_timer < FLP_INTERVAL_MAX_TIME)//not timeout
begin
if(autoNego_wait_timer > FLP_INTERVAL_MIN_TIME)
begin
if(link_code_rx_done_flag)
begin
autoNego_wait_timer <= 0;
flp_cnt <= flp_cnt + 1;
end
end
end
else //timeout, return to sleeping
begin
autoNego_wait_timer <= 0;
flp_cnt <= 0;
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
end
end
end







简单说就是

always@(posedge clk)
begin
a <= a+1;
if(a == 10)
a <= 0;
end

这个清零管用吗?




或者这么问:
always@(posedge clk)
begin
a<= 1;
a<= 2;
a<= 3;
end

最后a的值是多少?
...全文
2031 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
delacrxoix_xu 2012-03-15
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 costheta 的回复:]

【仅供参考,如有误导,概不负责】
下面的代码是我根据你的需求功能写的,当然也不是什么“标准写法”,仅仅是用于参考。
因为我没有测试过,如果功能与需求不符,可以作一点修改,但结构上是可用的。
无论是串行风格,还是并行风格,当写出一段verilog代码,一定要知道描述的是一个什么器件。

C/C++ code

// 超时标志
wire wait_timeout = autoNego_w……
[/Quote]


大大写的太好了!!!!!极其精彩!!在下佩服

大大是说我写的是 串行风格? 也就是说 c++软件设计的 思想还没退干净?
我设计硬件半年多了,感觉并行设计用太多,会导致顾不过来,分析起来不够清晰。但我没有说大大刚才的代码不清晰,那是精彩的。

我有这么个状态机,我写成一个了,具体的输出信号,有些是单独在另外的进程写的。也就是说1+n段描述。


大大帮忙分析下,状态机切换时候,我想清空一下当前状态下使用过的各个信号,如何写比较清晰和简洁?


功能描述: 自动协商的总状态机
sleep状态时候,计时,超时之后,发送检测脉冲。如果收到对方的检测脉冲,直接跳到 talking状态。
talking状态,接收到10个flp,之后进入almostdone状态。不满足,则返回sleep。
almostdone,置一个状态,第一次进入done状态,需要长时间的超时检测。
done状态,等待 pcs层模块的 linkup信号, 500ms超时, 如果超时,返回sleep。如果收到,则清空计时器,继续计时。



//*******************************************************************************
//AutoNego state machine
//reg [5 :0] state_m_autoNego_rx;
//reg [5: 0] flp_cnt;
//reg [28:0] autoNego_wait_timer;
//reg has_recv_three_LCW_flag;
//*******************************************************************************

reg [9:0] in_link_active_flag_copy;
always@(posedge CLK_10M or negedge n_reset_sync)
begin
if(0 == n_reset_sync)
in_link_active_flag_copy <= 0;
else
in_link_active_flag_copy <= {in_link_active_flag_copy[8:0],in_link_active_flag};
end

parameter STATE_NEGO_SLEEPING = 0;
parameter STATE_NEGO_DETECTING = 1;
parameter STATE_NEGO_TALKING = 2;
parameter STATE_NEGO_ALMOSTDONE = 4;
parameter STATE_NEGO_DONE = 8;



parameter FLP_INTERVAL_MIN_TIME = 5*10000; //8 ms
parameter FLP_INTERVAL_MAX_TIME = 24 * 10000; //24 ms
parameter AUTONEGO_WAIT_TIME = 1000 * 10000; //500 ~ 1000 ms
parameter AUTONEGO_TEST_TIMEOUT = 200 * 10000; //500 ~ 1000 ms
parameter AUTONEGO_ALMOSTDONE_TIMEOUT = 100 * 10000; //100 ~ 120 ms
parameter AUTONEGO_TEST_IDLE_TIMEOUT = 500 * 10000; //500ms
parameter AUTONEGO_LINK_FAIL_TIMEOUT = 100 * 10000; //100 ~ 120 ms

reg [31:0] autoNego_wait_timer;
reg test_idle_is_needed_flag;

always@(posedge CLK_10M or negedge n_reset_sync)
begin
if(0 == n_reset_sync)
begin
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
flp_cnt <= 0;
test_idle_is_needed_flag <= 1;
autoNego_wait_timer <= 0;
end
else
case(state_m_autoNego_rx)
STATE_NEGO_SLEEPING:
begin
autoNego_wait_timer <= autoNego_wait_timer + 1;
if(AUTONEGO_WAIT_TIME <= autoNego_wait_timer) //enough sleep. time to test
begin
autoNego_wait_timer <= 0;
flp_cnt <= 0;
state_m_autoNego_rx <= STATE_NEGO_DETECTING;
end
else
if( 1 == link_code_rx_done_flag) //or FLP detected. begin to work
begin
autoNego_wait_timer <= 0;
flp_cnt <= 1; //has received one LCW
state_m_autoNego_rx <= STATE_NEGO_TALKING;
end
end
STATE_NEGO_DETECTING:
begin
autoNego_wait_timer <= autoNego_wait_timer + 1;
if(AUTONEGO_TEST_TIMEOUT <= autoNego_wait_timer)
begin
autoNego_wait_timer <= 0;
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
end
else
if(1 == link_code_rx_done_flag)
begin
autoNego_wait_timer <= 0;
flp_cnt <= flp_cnt + 1;//has received one LCW, maybe tow
state_m_autoNego_rx <= STATE_NEGO_TALKING;
end
end
STATE_NEGO_TALKING:
begin
autoNego_wait_timer <= autoNego_wait_timer + 1;
if(flp_cnt > 10)
begin
autoNego_wait_timer <= 0;
state_m_autoNego_rx <= STATE_NEGO_ALMOSTDONE;
end
else
begin
if(autoNego_wait_timer < FLP_INTERVAL_MAX_TIME)//not timeout
begin
if(autoNego_wait_timer > FLP_INTERVAL_MIN_TIME)
begin
if(link_code_rx_done_flag)// another link_code_word is received
begin
autoNego_wait_timer <= 0;
flp_cnt <= flp_cnt + 1;
end
end
end
else //timeout, return to sleeping
begin
autoNego_wait_timer <= 0;
flp_cnt <= 0;
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
end
end
end
STATE_NEGO_ALMOSTDONE:
begin
test_idle_is_needed_flag <= 1;// test idle is needed, not yet linkup.
if( autoNego_wait_timer > AUTONEGO_ALMOSTDONE_TIMEOUT)
begin
state_m_autoNego_rx <= STATE_NEGO_DONE;
autoNego_wait_timer <= 0;
end
else
begin
autoNego_wait_timer <= autoNego_wait_timer + 1;
end
end
STATE_NEGO_DONE:
begin
if(0 == (&in_link_active_flag_copy[9:0]) ) //link not ready
begin
// first time coming here, need test idle.. 500ms timeout
// second time or more, needtest fail 100ms timeout
if( test_idle_is_needed_flag)
if(autoNego_wait_timer < AUTONEGO_TEST_IDLE_TIMEOUT)
autoNego_wait_timer <= autoNego_wait_timer + 1;
else
begin
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
flp_cnt <= 0;
autoNego_wait_timer <= 0;
end
else //!test_idle_is_needed_flag
if( autoNego_wait_timer < AUTONEGO_LINK_FAIL_TIMEOUT)
autoNego_wait_timer <= autoNego_wait_timer + 1;
else //timeout restart auto-negotiation
begin
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
flp_cnt <= 0;
autoNego_wait_timer <= 0;
end
end
else //linkup!! do nothing, just clear counter;
begin
autoNego_wait_timer <= 0;
//when linkup, clear the flag
test_idle_is_needed_flag <= 0;
end
end
default:
begin
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
flp_cnt <= 0;
autoNego_wait_timer <= 0;
end
endcase
end


//Gen has_recv_three_LCW_flag
always@(posedge CLK_10M or negedge n_reset_sync)
if(!n_reset_sync)
has_recv_three_LCW_flag <= 0;
else
has_recv_three_LCW_flag <= (state_m_autoNego_rx >= STATE_NEGO_TALKING && flp_cnt >= 3);



//Gen out_autoNego_done
always@(posedge CLK_10M or negedge n_reset_sync)
if(!n_reset_sync)
out_autoNego_done <= 0;
else
out_autoNego_done <= (STATE_NEGO_DONE == state_m_autoNego_rx || !in_autoNego_enable);





delacrxoix_xu 2012-03-15
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 costheta 的回复:]

把所有状态机驱动的变量揉在一起,看起来代码短一点,但不清晰。
如果状态机驱动变量很多,不要说几十个,就是十来个的话,估计就得把自己搅晕,
更不要说别人能看懂了。

下面的代码也只是我自己的风格,趁中午休息时写的,也没写全,
并且错误估计是有的,主要是为了示意,把自己的方法展现出来,以供探讨。

另:我只是个菜鸟,其实我的工作是写软件,偶尔客串一下FPGA。公司的FPGA工程师,估计……
[/Quote]

明白了,先给分,然后慢慢消化。谢谢高手了
costheta 2012-03-15
  • 打赏
  • 举报
回复
【仅供参考,如有误导,概不负责】
下面的代码是我根据你的需求功能写的,当然也不是什么“标准写法”,仅仅是用于参考。
因为我没有测试过,如果功能与需求不符,可以作一点修改,但结构上是可用的。
无论是串行风格,还是并行风格,当写出一段verilog代码,一定要知道描述的是一个什么器件。


// 超时标志
wire wait_timeout = autoNego_wait_timer >= FLP_INTERVAL_MAX_TIME;

// 有效flp脉冲,即在计数区间内到来的link_code_rx_done_flag
wire valid_flp_pulse = (autoNego_wait_timer < FLP_INTERVAL_MAX_TIME) &&
(autoNego_wait_timer > FLP_INTERVAL_MIN_TIME) &&
link_code_rx_done_flag;

// state_m_autoNego_rx -- 状态机:寄存器
always @( posedge clk ) begin
if( flp_cnt > 10 ) begin
state_m_autoNego_rx <= STATE_NEGO_ALMOSTDONE;
end
else if( wait_timeout ) begin
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
end
end

// flp_cnt -- flp事件计数: 带清零和使能的计数器
always @( posedge clk ) begin
if( wait_timeout ) begin
flp_cnt <= 0;
end
else if( valid_flp_pulse ) begin
flp_cnt <= flp_cnt + 1;
end
end

// autoNego_wait_timer -- 计时:带清零的计数器
always @( posedge clk ) beign
if( (flp_cnt > 10) || wait_timeout || valid_flp_pulse ) begin
autoNego_wait_timer <= 0;
end
else begin
autoNego_wait_timer <= autoNego_wait_timer + 1;
end
end
costheta 2012-03-15
  • 打赏
  • 举报
回复
把所有状态机驱动的变量揉在一起,看起来代码短一点,但不清晰。
如果状态机驱动变量很多,不要说几十个,就是十来个的话,估计就得把自己搅晕,
更不要说别人能看懂了。

下面的代码也只是我自己的风格,趁中午休息时写的,也没写全,
并且错误估计是有的,主要是为了示意,把自己的方法展现出来,以供探讨。

另:我只是个菜鸟,其实我的工作是写软件,偶尔客串一下FPGA。公司的FPGA工程师,估计都得有6年以上经验。之所以斗胆在在硬件版块充个数,主要是得分率高一点,挣一点分去换下载分:)

// 每个状态的超时计数值
reg [31:0] wait_timeout_value;
always @* begin
case( state_m_autoNego_rx )
STATE_NEGO_SLEEPING : wait_timeout_value = AUTONEGO_WAIT_TIME;
STATE_NEGO_DETECTING : wait_timeout_value = AUTONEGO_TEST_TIMEOUT;
STATE_NEGO_TALKING : wait_timeout_value = FLP_INTERVAL_MAX_TIME;
STATE_NEGO_ALMOSTDONE: wait_timeout_value = AUTONEGO_ALMOSTDONE_TIMEOUT;
STATE_NEGO_DONE : wait_timeout_value = test_idle_is_needed_flag ? AUTONEGO_TEST_IDLE_TIMEOUT : AUTONEGO_LINK_FAIL_TIMEOUT;
default : wait_timeout_value = 0;
endcase
end

// 有效flp脉冲,即在计数区间内到来的link_code_rx_done_flag
wire valid_flp_pulse = (autoNego_wait_timer < FLP_INTERVAL_MAX_TIME) &&
(autoNego_wait_timer > FLP_INTERVAL_MIN_TIME) &&
link_code_rx_done_flag;

// 状态转移:注重每个状态的转移条件
// 另:代码描述是异步复位,与命名_sync不符
always @(posedge CLK_10M, negedge n_reset_sync) begin
if( !n_reset_sync ) begin
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
end
else begin
case( state_m_autoNego_rx )
STATE_NEGO_SLEEPING: begin
if( autoNego_wait_timer > wait_timeout_value )
state_m_autoNego_rx <= STATE_NEGO_DETECTING;
end
else if( link_code_rx_done_flag ) begin
state_m_autoNego_rx <= STATE_NEGO_TALKING;
end
end

STATE_NEGO_DETECTING: begin
if( autoNego_wait_timer > wait_timeout_value )
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
end
else if( link_code_rx_done_flag ) begin
state_m_autoNego_rx <= STATE_NEGO_TALKING;
end
end

STATE_NEGO_TALKING: begin
if( flp_cnt > 10 ) begin
state_m_autoNego_rx <= STATE_NEGO_ALMOSTDONE;
end
else if( autoNego_wait_timer > wait_timeout_value ) begin
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
end
end

STATE_NEGO_ALMOSTDONE: begin
if( autoNego_wait_timer > wait_timeout_value ) begin
state_m_autoNego_rx <= STATE_NEGO_DONE;
end
end

STATE_NEGO_DONE: begin
if( (!(&in_link_active_flag_copy[9:0])) &&
(autoNego_wait_timer > wait_timeout_value) ) begin
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
end
end
end

default: state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
endcase
end
end

// 超时计数 : 注重每个状态下计数器的计数和清零条件
// 还可以写得更简化,不过这只是一种示意
always @(posedge CLK_10M, negedge n_reset_sync) begin
if( !n_reset_sync ) begin
autoNego_wait_timer <= 0;
end
else begin
case( state_m_autoNego_rx )
STATE_NEGO_SLEEPING: begin
if( autoNego_wait_timer > wait_timeout_value ) autoNego_wait_timer <= 0;
else autoNego_wait_timer <= autoNego_wait_timer + 1;
end

STATE_NEGO_DETECTING: begin
if( autoNego_wait_timer > wait_timeout_value ) autoNego_wait_timer <= 0;
else autoNego_wait_timer <= autoNego_wait_timer + 1;
end

STATE_NEGO_TALKING: begin
if( (flp_cnt > 10) ||
(autoNego_wait_timer > wait_timeout_value) ||
valid_flp_pulse )
autoNego_wait_timer <= 0;
else
autoNego_wait_timer <= autoNego_wait_timer + 1;
end

STATE_NEGO_ALMOSTDONE: begin
if( autoNego_wait_timer > wait_timeout_value ) autoNego_wait_timer <= 0;
else autoNego_wait_timer <= autoNego_wait_timer + 1;
end

STATE_NEGO_DONE: begin
if( (!(&in_link_active_flag_copy[9:0])) &&
(autoNego_wait_timer > wait_timeout_value) )
autoNego_wait_timer <= 0;
else
autoNego_wait_timer <= autoNego_wait_timer + 1;
end

default: autoNego_wait_timer <= 0;
endcase
end
end

//......

falloutmx 2012-03-15
  • 打赏
  • 举报
回复
这样纯粹是想到什么写什么的做法。我觉得costheta的写法很不错。
通常我会避免在一个always块里写太多的东西。把你的状态机改成2段或3段式,把激励的量合并一下,能清晰很多。
delacroix_xu1 2012-03-14
  • 打赏
  • 举报
回复
不能连续回复三次。。。上小号



begin
autoNego_wait_timer <= autoNego_wait_timer + 1;
if(flp_cnt > 10)
begin
autoNego_wait_timer <= 0;
state_m_autoNego_rx <= STATE_NEGO_ALMOSTDONE;
end
else
begin
if(autoNego_wait_timer < FLP_INTERVAL_MAX_TIME)//not timeout
begin
if(autoNego_wait_timer > FLP_INTERVAL_MIN_TIME)
begin
if(link_code_rx_done_flag)
begin
autoNego_wait_timer <= 0;
flp_cnt <= flp_cnt + 1;
end
end
end
else //timeout, return to sleeping
begin
autoNego_wait_timer <= 0;
flp_cnt <= 0;
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
end
end



刚才的代码对其有问题,大家帮忙看看这个,应该怎么写,感觉用标准写法,特别费劲。

逻辑功能: 计数器不停计数, 一旦超时了,状态机就回到 sleep状态, 当flp脉冲序列在 min 和max 时间之内到来时, 将flp数量计数器加1 ,并重置 计时器。 当flp接收足够10个时,状态机跳转到 done 状态,同时清空计时器。
costheta 2012-03-13
  • 打赏
  • 举报
回复
【仅供参考,如有误导,概不负责】

这涉及到非阻塞赋值本身的语义。
当事件发生时,对于代码块中的非阻塞赋值语句,先计算所有非阻塞语句在【事件发生时刻】的值,(即以<=右端表达式的值),最后才把计算出的值赋给<=左边的变量。
计算过程是以代码块中语句的书写顺序进行。虽有先后顺序,但<=右端表达式中变量的值均为【事件发生时刻】时的值。

always @(posedge clk) begin // 时间点:clk上升沿事件发生时刻
a <= 1; // 事件发生时刻,a_temp = 1
a <= 2; // 事件发生时刻,a_temp = 2
a <= 3; // 事件发生时刻,a_temp = 3
end
// 在事件完成时刻,更新变量a的值 a = a_temp = 3


同一语句块中非阻塞重复赋值,虽然符合语法语义,但应杜绝出在在设计中。考察下面两语句块

// 这段代码可以实现计数和清0
// 第2句只在条件满足时才对a_temp赋值为0,其它时候取第1句的赋值
always @(posedge clk) begin
a <= a + 1; // 事件发生时刻,a_temp =【事件发生时刻的a】+ 1
if( a == 10 ) a <= 0; // 事件发生时刻,if(【事件发生时刻的a】== 10 ) a_temp = 0
end

// 这段代码只能实现计数,不能实现清零。
// 第2句任何时候都会再次对a_temp赋值为a+1,相当于第1句任何时候都不起作用
always@(posedge clk) begin
if( a == 10 ) a <= 0; // 事件发生时刻,if(【事件发生时刻的a】== 10 ) a_temp = 0
a <= a + 1; // 事件发生时刻,a_temp =【事件发生时刻的a】+ 1
end
delacrxoix_xu 2012-03-13
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 junjun1894 的回复:]

C/C++ code

always@(posedge clk) begin
if( a == 10 ) a <= 0;
else a <= a + 1;
end
[/Quote]

这个我知道,应该这么写,但是复杂的情况,你会写很多 else a <= a + 1; 会浪费很多行代码,其他人也理解着费劲
delacrxoix_xu 2012-03-13
  • 打赏
  • 举报
回复

begin
autoNego_wait_timer <= autoNego_wait_timer + 1;
if(flp_cnt > 10)
begin
autoNego_wait_timer <= 0;
state_m_autoNego_rx <= STATE_NEGO_ALMOSTDONE;
end
else
begin
if(autoNego_wait_timer < FLP_INTERVAL_MAX_TIME)//not timeout
begin
if(autoNego_wait_timer > FLP_INTERVAL_MIN_TIME)
begin
if(link_code_rx_done_flag)
begin
autoNego_wait_timer <= 0;
flp_cnt <= flp_cnt + 1;
end
end
end
else //timeout, return to sleeping
begin
autoNego_wait_timer <= 0;
flp_cnt <= 0;
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
end
end
delacrxoix_xu 2012-03-13
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 costheta 的回复:]

【仅供参考,如有误导,概不负责】

这涉及到非阻塞赋值本身的语义。
当事件发生时,对于代码块中的非阻塞赋值语句,先计算所有非阻塞语句在【事件发生时刻】的值,(即以<=右端表达式的值),最后才把计算出的值赋给<=左边的变量。
计算过程是以代码块中语句的书写顺序进行。虽有先后顺序,但<=右端表达式中变量的值均为【事件发生时刻】时的值。
C/C++ code

always @(posed……
[/Quote]

begin
autoNego_wait_timer <= autoNego_wait_timer + 1;
if(flp_cnt > 10)
begin
autoNego_wait_timer <= 0;
state_m_autoNego_rx <= STATE_NEGO_ALMOSTDONE;
end
else
begin
if(autoNego_wait_timer < FLP_INTERVAL_MAX_TIME)//not timeout
begin
if(autoNego_wait_timer > FLP_INTERVAL_MIN_TIME)
begin
if(link_code_rx_done_flag)
begin
autoNego_wait_timer <= 0;
flp_cnt <= flp_cnt + 1;
end
end
end
else //timeout, return to sleeping
begin
autoNego_wait_timer <= 0;
flp_cnt <= 0;
state_m_autoNego_rx <= STATE_NEGO_SLEEPING;
end
end
end


如果我这些代码按照标准来写,会多占用很多行代码,是吧?
junjun1894 2012-03-13
  • 打赏
  • 举报
回复

always@(posedge clk) begin
if( a == 10 ) a <= 0;
else a <= a + 1;
end

6,167

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 硬件设计
社区管理员
  • 硬件设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧