HDLBits答案(18)_Verilog有限状态机(5)
Verilog有限狀態(tài)機(jī)(5)
HDLBits鏈接
前言
今天繼續(xù)更新狀態(tài)機(jī)小節(jié)的習(xí)題。
題庫
題目描述1:
第一道題目比較容易,題目中的in信號包含了一個起始位(0),8個數(shù)據(jù)位和一個停止位(1),開始in為1,也就是IDLE狀態(tài),當(dāng)in為0時,進(jìn)入START狀態(tài),然后經(jīng)過8個周期,如果in為1,則進(jìn)入STOP狀態(tài),接著如果in為0,進(jìn)入第二輪START狀態(tài),否則進(jìn)入IDLE狀態(tài)。
這里我用了很多個狀態(tài),實(shí)際上可以用計(jì)數(shù)器來代替中間的8個狀態(tài),這里是8個周期,如果是100個、200個周期,那么需要100個、200個狀態(tài),顯然不現(xiàn)實(shí)。這道題目是三道題目中的基礎(chǔ)題,大家不用考慮那么多,直接完成就好了。
Solution1:
module top_module(input clk,input in,input reset, // Synchronous resetoutput done ); parameter [3:0] START = 4'd0;parameter [3:0] ONE = 4'd1;parameter [3:0] TWO = 4'd2;parameter [3:0] THREE = 4'd3;parameter [3:0] FOUR = 4'd4;parameter [3:0] FIVE = 4'd5;parameter [3:0] SIX = 4'd6;parameter [3:0] SEVEN = 4'd7;parameter [3:0] EIGHT = 4'd8;parameter [3:0] STOP = 4'd9;parameter [3:0] IDLE = 4'd10;parameter [3:0] WAIT = 4'd11;reg [3:0] state,next_state;always @(*)begincase(state)START:beginnext_state <= ONE;endONE:beginnext_state <= TWO;endTWO:beginnext_state <= THREE;endTHREE:beginnext_state <= FOUR;endFOUR:beginnext_state <= FIVE;endFIVE:beginnext_state <= SIX;endSIX:beginnext_state <= SEVEN;endSEVEN:beginnext_state <= EIGHT;endEIGHT:beginif(in)beginnext_state <= STOP;endelse beginnext_state <= WAIT;endendSTOP:beginif(in)beginnext_state <= IDLE;endelse beginnext_state <= START;endendWAIT:beginif(in)beginnext_state <= IDLE;endelse beginnext_state <= WAIT;endendIDLE:beginif(~in)beginnext_state <= START;endelse beginnext_state <= IDLE;endendendcaseendalways @(posedge clk)beginif(reset)beginstate <= IDLE;endelse beginstate <= next_state;endendassign done = (state == STOP);endmodule題目描述2:
這道題目是上一道題目的擴(kuò)展,不僅需要輸出done信號,還需要輸出數(shù)據(jù)。
Solution2:
/* way 1*/ module top_module(input clk,input in,input reset, // Synchronous resetoutput [7:0] out_byte,output done ); //parameter [3:0] START = 4'd0;parameter [3:0] ONE = 4'd1;parameter [3:0] TWO = 4'd2;parameter [3:0] THREE = 4'd3;parameter [3:0] FOUR = 4'd4;parameter [3:0] FIVE = 4'd5;parameter [3:0] SIX = 4'd6;parameter [3:0] SEVEN = 4'd7;parameter [3:0] EIGHT = 4'd8;parameter [3:0] STOP = 4'd9;parameter [3:0] IDLE = 4'd10;parameter [3:0] WAIT = 4'd11;reg [3:0] state,next_state;reg [7:0] par_in;always @(*)begincase(state)START:beginnext_state <= ONE;par_in[0] <= in;endONE:beginnext_state <= TWO;par_in[1] <= in;endTWO:beginnext_state <= THREE;par_in[2] <= in;endTHREE:beginnext_state <= FOUR;par_in[3] <= in;endFOUR:beginnext_state <= FIVE;par_in[4] <= in;endFIVE:beginnext_state <= SIX;par_in[5] <= in;endSIX:beginnext_state <= SEVEN;par_in[6] <= in;endSEVEN:beginnext_state <= EIGHT;par_in[7] <= in;endEIGHT:beginif(in)beginnext_state <= STOP;endelse beginnext_state <= WAIT;endendSTOP:beginif(in)beginnext_state <= IDLE;endelse beginnext_state <= START;endendWAIT:beginif(in)beginnext_state <= IDLE;endelse beginnext_state <= WAIT;endendIDLE:beginif(~in)beginnext_state <= START;endelse beginnext_state <= IDLE;endendendcaseendalways @(posedge clk)beginif(reset)beginstate <= IDLE;endelse beginstate <= next_state;endendassign done = (state == STOP);assign out_byte = (state == STOP) ? par_in : 8'd0;endmodule/* way 2 */ module top_module(input clk,input in,input reset, // Synchronous resetoutput [7:0] out_byte,output done ); parameter IDLE = 3'd0, START = 3'd1, DATA = 3'd2;parameter STOP = 3'd3, WAIT = 3'd4;reg [3:0] current_state;reg [3:0] next_state;reg [3:0] counter;reg [7:0] par_in;// Use FSM from Fsm_serialalways @(*)begincase(current_state)IDLE:beginif(~in)beginnext_state = START;endelse beginnext_state = IDLE;endendSTART:beginnext_state = DATA;endDATA:beginif(counter == 4'd8)beginnext_state = in? STOP:WAIT;endelse beginnext_state = DATA;endendSTOP:beginnext_state = in? IDLE:START;endWAIT:beginnext_state = in? IDLE:WAIT;enddefault:beginnext_state = IDLE;endendcaseendalways @(posedge clk)beginif(reset)begincurrent_state <= IDLE;endelse begincurrent_state <= next_state;endendalways @(posedge clk)beginif(reset)begindone <= 1'd0;out_byte <= 8'd0;counter <= 4'd0;endelse begincase(next_state)IDLE:begindone <= 1'd0;out_byte <= 8'd0;counter <= 4'd0;endSTART:begindone <= 1'd0;out_byte <= 8'd0;counter <= 4'd0;endDATA:begindone <= 1'd0;out_byte <= 8'd0;par_in[counter] <= in;counter <= counter + 1'd1;endSTOP:begindone <= 1'd1;out_byte <= par_in;counter <= 4'd0;endWAIT:begindone <= 1'd0;out_byte <= 8'd0;counter <= 4'd0;endendcaseendend// New: Datapath to latch input bits.endmodule上述第一種解法雖然正確,但是會生成鎖存器,并且這里只有1個字節(jié)數(shù)據(jù)還好,用8個狀態(tài)是可以的,如果換成了10個字節(jié)、100個字節(jié),難道要80、800個狀態(tài)嗎?這是不可能的,于是便誕生了方法二博主最想讓大家使用的方法。大家可以好好看一下,這里將8個數(shù)據(jù)狀態(tài)定義成了一個DATA狀態(tài),不用定義S1、S2、S3什么的了,在狀態(tài)機(jī)的第三段,將除了DATA狀態(tài)的其他狀態(tài)時的counter都清零,只有到了DATA狀態(tài)時開始計(jì)數(shù),順便將par_in中的位數(shù)用counter代替,這樣只需要增加counter和out_byte的位寬,就可以實(shí)現(xiàn)任意寬度數(shù)據(jù)的輸出,實(shí)用性強(qiáng)。
題目描述3:
較上題添加了奇偶校驗(yàn)位。
module top_module(input clk,input in,input reset, // Synchronous resetoutput [7:0] out_byte,output done ); //parameter IDLE = 3'd0,START = 3'd1,DATA = 3'd2;parameter STOP = 3'd3,WAIT = 3'd4;reg [2:0] current_state,next_state;reg [3:0] counter;reg [8:0] data_in;reg odd_temp;wire Isdone;// Modify FSM and datapath from Fsm_serialdataalways @(*) begincase(current_state)IDLE:beginif(~in)beginnext_state = START;endelse beginnext_state = IDLE;endendSTART:beginnext_state = DATA;endDATA:beginif(counter == 4'd9)beginnext_state = in ? STOP : WAIT;endelse beginnext_state = DATA;endendSTOP:beginnext_state = in ? IDLE : START;endWAIT:beginnext_state = in ? IDLE : WAIT;enddefault:beginnext_state = IDLE;endendcaseendalways @(posedge clk) beginif(reset)begincurrent_state <= IDLE;endelse begincurrent_state <= next_state;endendalways @(posedge clk) beginif(reset)begindone <= 1'd0;out_byte <= 8'd0;counter <= 4'd0;endelse begincase(next_state)IDLE:begindone <= 1'd0;out_byte <= 8'd0;counter <= 4'd0;endSTART:begindone <= 1'd0;out_byte <= 8'd0;counter <= 4'd0;endDATA:begindone <= 1'd0;out_byte <= 8'd0;counter <= counter + 1'd1;data_in[counter] <= in;endSTOP:begindone <= odd_temp ? 1'd1 : 1'd0;out_byte <= odd_temp ? data_in[7:0] : 8'd0;counter <= 4'd0;endWAIT:begindone <= 1'd0;out_byte <= 8'd0;counter <= 4'd0;endendcaseendend// New: Add parity checking.assign Isdone = (next_state == START);parity u0(clk,Isdone,in,odd_temp);endmodule該題答案與上題類似,這里我將奇偶校驗(yàn)位數(shù)據(jù)也計(jì)算在DATA狀態(tài)內(nèi),判斷起來相對較容易,大家可以借鑒一下。
注意作者在題目中給了奇偶校驗(yàn)的模塊,大家直接調(diào)用即可。
結(jié)語
好久沒更新HDLBits了,寒假在家閑來無事,希望勉勵自己把HDLBits刷完吧,加油!有問題的地方歡迎大家與我討論交流。
總結(jié)
以上是生活随笔為你收集整理的HDLBits答案(18)_Verilog有限状态机(5)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: Modelsim10.7中文注释乱码问题
 - 下一篇: HDLBits答案(19)_Verilo