FSM ps2
题目:The PS/2 mouse protocol sends messages that are three bytes long. However, within a continuous byte stream, it’s not obvious where messages start and end. The only indication is that the first byte of each three byte message always has bit[3]=1 (but bit[3] of the other two bytes may be 1 or 0 depending on data).
We want a finite state machine that will search for message boundaries when given an input byte stream. The algorithm we’ll use is to discard bytes until we see one with bit[3]=1. We then assume that this is byte 1 of a message, and signal the receipt of a message once all 3 bytes have been received (done).
The FSM should signal done in the cycle immediately after the third byte of each message was successfully received.
分析:
- 下图状态转移图钟的BYTE1,BYTE2,BYTE3和上图波形图中的不对应,上图收到起始符时已经是BYTE1,我的状态转移图在收到起始符后才变为BYTE1;
- 在BYTE3之后需要进行判断,如果是in[3]==1开始进行技术,在IDLE,BYTE1,BYTE2三个阶段则会收到全部的三个数据,BYTE3状态下收到的其实是下一数据的判断位,因此需要直接进行判断,如果此时in[3]==1,则直接进入下一个数据的接受周期;
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output done); //
parameter IDLE=2'b00;
parameter BYTE1=2'b01;
parameter BYTE2=2'b10;
parameter BYTE3=2'b11;
reg [1:0] state, next_state;
//状态寄存器 state flip-flops (sequential)
always @(posedge clk) begin
if (reset) state<=IDLE;
else state<=next_state;
end
//状态转移逻辑
always @(*) begin
case(state)
IDLE: begin
if (in[3]==1'b1) next_state=BYTE1;
else next_state=IDLE;
end
BYTE1: begin
next_state=BYTE2;
end
BYTE2: begin
next_state=BYTE3;
end
BYTE3: begin
next_state=(in[3]==1'b1)?BYTE1:IDLE;
end
endcase
end
//输出逻辑 output
always @(*) begin
if (reset) done<=1'b0;
else if (state == BYTE3) done<=1'b1;
else done<=1'b0;
end
endmodule
FSM ps2data
题目:Now that you have a state machine that will identify three-byte messages in a PS/2 byte stream, add a datapath that will also output the 24-bit (3 byte) message whenever a packet is received (out_bytes[23:16] is the first byte, out_bytes[15:8] is the second byte, etc.).
out_bytes needs to be valid whenever the done signal is asserted. You may output anything at other times (i.e., don’t-care).
分析:
和上题一样的状态机设置时,BYTE3进行done信号和out_bytes数据的输出,此时依然有可能正在接收着作为下一个周期的第一位数据,在这种情况下是没有IDLE状态来接收第一个数据的,而是直接进入BYTE1。因此,需要一个flip-flop暂存BYTE3时的数据,如果之后紧接着一个数据周期的话,则将这个寄存器中的数据存入原本的out_temp[23:16]
可以看出,如果前后两个数据没有相连,是可以存在IDLE状态的,此时则可以正常接收第一个数据,也就是out_temp[23:16]。具体的代码逻辑如下图所示:
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output [23:0] out_bytes,
output done); //
// FSM from fsm_ps2
// definition for states
parameter IDLE=2'b00;
parameter BYTE1=2'b01;
parameter BYTE2=2'b10;
parameter BYTE3=2'b11;
reg [1:0] state, next_state;
reg [23:0] out_temp;
// flip-flops (synchronous reset)
always@(posedge clk) begin
if (reset) state<=IDLE;
else state<=next_state;
end
// state transition
always@(*) begin
case (state)
IDLE: begin
if (in[3]==1'b1) next_state=BYTE1;
else next_state=IDLE;
end
BYTE1:begin
next_state=BYTE2;
//out_temp[23:16]=in[7:0];
end
BYTE2:begin
next_state=BYTE3;
//out_temp[15:8]=in[7:0];
end
BYTE3: begin
//out_temp[7:0]=in[7:0];
if(in[3]==1'b1) next_state=BYTE1;
else next_state=IDLE;
end
endcase
end
//output logic
always@(*) begin
if (reset) begin
done=1'b0;
out_bytes=24'bx;
end
else if (state==BYTE3) begin
done=1'b1;
out_bytes=out_temp;
end
else done=1'b0;
end
// New: Datapath to store incoming bytes.
reg [7:0] in_r;
reg [1:0] state_r;
always@(posedge clk) begin
if (reset) begin
in_r<=8'b0;
state_r<=IDLE;
end
else begin
state_r<=state;
in_r<=in;
end
end
always@(*) begin
case (state)
IDLE: begin
if (in[3]==1'b1) out_temp[23:16]=in;
end
BYTE1: begin
if (state_r==BYTE3 && in_r[3]==1'b1) begin
out_temp[15:8]=in;
out_temp[23:16]=in_r;
end
else out_temp[15:8]=in;
end
BYTE2: begin
out_temp[7:0]=in;
end
BYTE3: begin
;
end
default: begin
;
end
endcase
end
endmodule