相關文章
Verilog基礎
https://blog.csdn.net/weixin_45791458/category_12263729.html?spm=1001.2014.3001.5482
? ? ? ? Verilog中的寄存器操作一般指的是那些對時鐘沿敏感而且使用非阻塞賦值的操作。例如狀態機中的狀態轉移,實際上就是一種寄存器操作,因為這相當于將下一狀態的組合邏輯連接至寄存器的輸入,如圖一的Moore狀態機所示。

圖1 Moore型狀態機
? ? ? ? 對于這種的寄存器操作,三段式的描述方式清清晰明了地將組合邏輯和寄存器操作分離,所以被廣泛接受的,如下所示。
//第一段,下一狀態組合邏輯
always@(*) begincase (state) ***: next_state = ***;***: next_state = ***;endcase
end//第二段,狀態轉移時序邏輯
always @(posedge clk, negedge rst_n) beginif (!rst_n) state <= ***; else state <= next_state;
end//第三段,輸出組合邏輯
always@(*) beginif(state == ***)out = ***;elseout = ***;
end
? ? ? ? 但對于需要輸出寄存的情況,就可能出現兩種不同的描述寄存器操作的風格,一種是組合邏輯和寄存器操作分離,就像狀態轉移一樣,另一種是將組合邏輯和寄存器操作混合在一起。下面是一個簡單的例子。
//將輸出組合邏輯和輸出寄存分離
//第一段,下一狀態組合邏輯
always@(*) begincase (state) ***: next_state = ***;***: next_state = ***;endcase
end//第二段,狀態轉移時序邏輯
always @(posedge clk, negedge rst_n) beginif (!rst_n) state <= ***; else state <= next_state;
end//第三段,輸出組合邏輯
always@(*) beginif(state == ***)out = ***;elseout = ***;
end//第四段,輸出寄存時序邏輯
always @(posedge clk, negedge rst_n) beginif (!rst_n) out_r <= ***; else out_r <= out;
end
endmodule
?
//將輸出組合邏輯和輸出寄存融合
//第一段,下一狀態組合邏輯
always@(*) begincase (state) ***: next_state = ***;***: next_state = ***;endcase
end//第二段,狀態轉移時序邏輯
always @(posedge clk, negedge rst_n) beginif (!rst_n) state <= ***; else state <= next_state;
end//第三段,輸出寄存時序邏輯
always @(posedge clk, negedge rst_n) beginif (!rst_n) out_r <= ***; else out_r <= ***;
end
endmodule
? ? ? ? 對于狀態機簡單的輸出寄存,可以將輸出組合邏輯和輸出寄存融合,比如計數器(對計數器而言狀態就是輸出,所以也可以理解為將狀態轉移也融合進來了)。同時對于一般簡單的寄存器操作比如移位,也可以將輸出組合邏輯和輸出寄存融合。
//組合邏輯和寄存器操作融合
always@(posedge clk or negedge rst_n) beginif(!rst_n)cnt <= 0;elsecnt <= cnt + 1;
end//組合邏輯和寄存器操作不融合
always@(posedge clk or negedge rst_n) beginif(!rst_n)cnt <= 0;elsecnt <= cnt_pre;
assign cnt_pre = cnt + 1;
end//簡單的寄存器操作,組合邏輯和時序邏輯融合
always@(posedge clk or negedge rst_n) beginif(!rst_n)shift <= 0;else if(load)shift <= shift_load;elseshift <= shift << 1;
end//簡單的寄存器操作,組合邏輯和時序邏輯不融合
always@(posedge clk or negedge rst_n) beginif(!rst_n)shift <= 0;else if(load)shift <= shift_load;elseshift <= shift_pre;
endassign shift_pre = shift << 1;