總共兩個狀態:

(1)一段式(時序邏輯)
原始碼://狀態控制信號用計數器計數產生
always@(posedge clk or negedge rst_n)
if(!rst_n) begin
cnt <= 5'd0;
ed <= 1'b0;
jump <= 1'b0;
end
else if(cnt == 5'd10) begin
ed <= 1'b1;
cnt <= cnt + 1'b1;
end
else if(cnt == 5'd20) begin
jump <= 1'b1;
cnt <= 5'd0;
end
else begin
cnt <= cnt + 1'b1;
ed <= 1'b0;
jump <= 1'b0;
End
//一段式狀態機
always@(posedge clk or negedge rst_n)
if(!rst_n) begin
state <= wr;
p <= 1'b0;
q <= 1'b0;
end
else begin
case(state)
wr:begin
if(ed) begin
state <= rd;
q <= 1;
end
else begin
state <= wr;
q <= 0;
end
end
rd:begin
if(jump) begin
state <= wr;
p <= 1;
end
else begin
state <= rd;
p <= 0;
end
end
endcase
end
波形圖:

決議:當計數器計到10時,ed信號不能馬上變為1,需要等待下一個時鐘上升沿到來時才能變為1;當ed信號變為1后,state也不能馬上轉到下一個狀態,也需要等待下一個時鐘上升沿,當state從0變為1后,q緊跟著也變為1,因為代碼中標黃那兩句是順序執行的,幾乎沒有延時。
(2)一段式(組合邏輯)
原始碼://計數器和ed、jump賦值
assign ed = (cnt == 5'd10)?1'b1:1'b0;
assign jump = (cnt == 5'd20)?1'b1:1'b0;
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 5'd0;
else if(cnt == 5'd20)
cnt <= 5'd0;
else
cnt <= cnt + 1'b1;
//一段式狀態機
always@(posedge clk or negedge rst_n)
if(!rst_n) begin
state <= wr;
p <= 1'b0;
q <= 1'b0;
end
else begin
case(state)
wr:begin
if(ed) begin
state <= rd;
q <= 1;
end
else begin
state <= wr;
q <= 0;
end
end
rd:begin
if(jump) begin
state <= wr;
p <= 1;
end
else begin
state <= rd;
p <= 0;
end
end
endcase
end
波形圖:

決議:當計數器計到10的時候,因為組合邏輯賦值(非阻塞賦值)不需要等待時鐘上升沿,所以在計數器計到10時,ed信號立馬變成了1。當ed信號變為1后,state也不能馬上轉到下一個狀態,也需要等待下一個時鐘上升沿,當state從0變為1后,q緊跟著也變為1,因為代碼中標黃那兩句是順序執行的,幾乎沒有延時。
(3)三段式(第三段case(n_state))
原始碼://計數器和ed、jump賦值
always@(posedge clk or negedge rst_n)
if(!rst_n) begin
cnt <= 5'd0;
ed <= 1'b0;
jump <= 1'b0;
end
else if(cnt == 5'd10) begin
ed <= 1'b1;
cnt <= cnt + 1'b1;
end
else if(cnt == 5'd20) begin
jump <= 1'b1;
cnt <= 5'd0;
end
else begin
cnt <= cnt + 1'b1;
ed <= 1'b0;
jump <= 1'b0;
end
//第一段(對c_state賦值)
always@(posedge clk or negedge rst_n)
if(!rst_n)
c_state <= wr;
else
c_state <= n_state;
//第二段(組合邏輯,對n_state賦值)
always@(*)
case(c_state)
wr:
if(ed)
n_state <= rd;
else
n_state <= wr;
rd:
if(jump)
n_state <= wr;
else
n_state <= rd;
endcase
//第三段(對p、q賦值)
always@(posedge clk or negedge rst_n)
if(!rst_n) begin
p <= 1'b0;
q <= 1'b0;
end
else begin
case(n_state)
wr:
if(ed)
p <= 1;
else
p <= 0;
rd:
if(jump)
q <= 1;
else
q <= 0;
endcase
end
波形圖:

決議:當計數器計到10時,ed信號不能馬上變為1,需要等待下一個時鐘上升沿到來時才能變為1;當ed信號變為1的時候,狀態接的第二段因為是組合邏輯,所以n_state會立馬變成下一個狀態1;但是第一段是時序邏輯,所以c_state需要等待下一個時鐘沿才會變化為下一個狀態;因為在第三段中的case是(n_state),所以當ed信號變為1的時候,n_state已經變成了rd(1)狀態,所以q變化的條件已經不滿足了。
(4)三段式case(第三段case(c_state))
原始碼://計數器和ed、jump賦值
always@(posedge clk or negedge rst_n)
if(!rst_n) begin
cnt <= 5'd0;
ed <= 1'b0;
jump <= 1'b0;
end
else if(cnt == 5'd10) begin
ed <= 1'b1;
cnt <= cnt + 1'b1;
end
else if(cnt == 5'd20) begin
jump <= 1'b1;
cnt <= 5'd0;
end
else begin
cnt <= cnt + 1'b1;
ed <= 1'b0;
jump <= 1'b0;
end
//第一段(對c_state賦值)
always@(posedge clk or negedge rst_n)
if(!rst_n)
c_state <= wr;
else
c_state <= n_state;
//第二段(組合邏輯,對n_state賦值)
always@(*)
case(c_state)
wr:
if(ed)
n_state <= rd;
else
n_state <= wr;
rd:
if(jump)
n_state <= wr;
else
n_state <= rd;
endcase
//第三段(對p、q賦值)
always@(posedge clk or negedge rst_n)
if(!rst_n) begin
p <= 1'b0;
q <= 1'b0;
end
else begin
case(c_state)
wr:
if(ed)
p <= 1;
else
p <= 0;
rd:
if(jump)
q <= 1;
else
q <= 0;
endcase
end
波形圖:

決議:當計數器計到10時,ed信號不能馬上變為1,需要等待下一個時鐘上升沿到來時才能變為1;當ed信號變為1的時候,狀態接的第二段因為是組合邏輯,所以n_state會立馬變成下一個狀態1;但是第一段是時序邏輯,所以c_state需要等待下一個時鐘沿才會變化為下一個狀態;當下一個時鐘到來的時候,因為所有的always塊都是并行的,所以第一段和第三段是同時執行的,所以ed=1時,c_state變為下一個狀態(第一段執行),同時,q=1(第三段執行);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/47398.html
標籤:其他硬件開發
上一篇:STM32移植ucos的一點疑問
