目录
题目3:Fsm ps2data(ps/2数据包解析器和数据路径)
题目1:Fsm onehot(热编码的有限状态机)
给定以下状态机,具有 1 个输入和 2 个输出:
假设此状态机使用单热编码,其中状态[0]通过状态[9]分别对应于状态S0和S9。除非另有指定,否则输出为零。
实现状态机的状态转换逻辑和输出逻辑部分(但不是状态触发器)。在状态[9:0]中,您将获得当前状态,并且必须产生next_state[9:0]和两个输出。通过检查假设一热编码来推导逻辑方程。(测试平台将使用非一个热输入进行测试,以确保您不会尝试执行更复杂的操作)。
模块声明
module top_module( input in, input [9:0] state, output [9:0] next_state, output out1, output out2);
提示:一热状态转换逻辑的逻辑方程可以通过查看状态转换图的边缘来推导。
根据状态流程图写出逻辑关系,输出也是一样的道理。
module top_module(
input in,
input [9:0] state,
output [9:0] next_state,
output out1,
output out2);
parameter s0 =4'd0,s1 = 4'd1,s2 = 4'd2,s3 = 4'd3,s4 = 4'd4,s5 = 4'd5,s6 = 4'd6,s7 = 4'd7,s8 = 4'd8,s9 = 4'd9;
//状态逻辑
assign next_state[s0] = !in &( state[s0] | state[s1] | state[s2] | state[s3] | state[s4] | state[7] | state[s8] | state[s9]);
assign next_state[s1] = in &( state[s0] | state[s8] | state[s9]);
assign next_state[s2] = in &( state[s1]);
assign next_state[s3] = in & state[s2] ;
assign next_state[s4] = in & state[s3] ;
assign next_state[s5] = in & state[s4] ;
assign next_state[s6] = in & state[s5] ;
assign next_state[s7] = in & (state[s6] | state[7]);
assign next_state[s8] = !in & state[s5] ;
assign next_state[s9] = !in & state[s6] ;
//输出逻辑
assign out1 = state[8]|state[9];
assign out2 = state[7]|state[9];
endmodule
仿真结果:
题目2:Fsm ps2(ps/2数据包解析器)
PS/2 鼠标协议发送长度为 3 个字节的消息。但是,在连续字节流中,消息的开始和结束位置并不明显。唯一的指示是,每个三字节消息的第一个字节始终具有 bit[3]=1(但其他两个字节的位 [3] 可能是 1 或 0,具体取决于数据)。
我们想要一个有限的状态机,当给定输入字节流时,它将搜索消息边界。我们将使用的算法是丢弃字节,直到我们看到一个位[3]=1的字节。然后,我们假设这是消息的字节 1,并在收到所有 3 个字节(完成)后发出接收消息的信号。
FSM 应在成功接收到每条消息的第三个字节后立即在周期内发出信号。
一些时序图来解释所需的行为
在无差错条件下,每三个字节形成一条消息:
发生错误时,搜索字节 1:
请注意,这与 1xx 序列识别器不同。此处不允许使用重叠序列:
模块声明
module top_module( input clk, input [7:0] in, input reset, // Synchronous reset output done);
代码编写如下:
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output done); //
reg [1:0] state,next_state;
parameter s0 = 2'd0,s1 = 2'd1,s2 = 2'd2,s3 = 2'd3;
// State transition logic (combinational),组合逻辑
always @(*)
begin
case(state)
s0:begin;
if(!in[3])
next_state = s0;
else
next_state = s1;
end
s1: next_state = s2;
s2: next_state = s3;
s3:begin
if(!in[3])
next_state = s0;
else
next_state = s1;
end
endcase
end
// State flip-flops (sequential),时序逻辑
always @(posedge clk)
begin
if(reset)
state <= s0;
else
state <= next_state;
end
// Output logic,输出逻辑
assign done = (state==s3);
endmodule
题目3:Fsm ps2data(ps/2数据包解析器和数据路径)
另请参见:PS/2 数据包解析器。
现在,您已经有了一个状态机,它将识别 PS/2 字节流中的三字节消息,请添加一个数据路径,该数据路径还将在收到数据包时输出 24 位(3 字节)消息(out_bytes[23:16] 是第一个字节,out_bytes[15:8] 是第二个字节,依此类推)。
每当断言完成信号时,out_bytes都需要有效。您可以在其他时间输出任何内容(即,不要在乎)。
模块声明
module top_module( input clk, input [7:0] in, input reset, // Synchronous reset output [23:0] out_bytes, output done);
分析:观察所给的图例,当done=1,in位1时,输出24位才有效。当in为1,done为1,输出out——bytes才依次从高8位,中8位,低8位输出。当done为0时,不关心输出。
代码如下:
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output [23:0] out_bytes,
output done); //
reg [1:0] state,next_state;
parameter [1:0] s0 = 2'd0,s1 = 2'd1,s2 = 2'd2 ,s3 = 2'd3;
// FSM from fsm_ps2
always @(*)
begin
case(state)
s0:begin
if(!in[3])
next_state = s0;
else
next_state = s1;
end
s1:next_state = s2;
s2:next_state = s3;
s3:begin
if(!in[3])
next_state = s0;
else
next_state = s1;
end
endcase
end
// New: Datapath to store incoming bytes.
always @(posedge clk)
begin
if(reset)
state <= s0;
else
state <= next_state ;
end
always @(posedge clk)
begin
if(next_state == s1) begin
out_bytes[23:16] <= in;
end
else if(next_state == s2)
begin
out_bytes[15:8] <= in;
end
else if(next_state == s3)
begin
out_bytes[7:0] <= in;
end
else begin
out_bytes <= 24'b0;
end
end
assign done = (state == s3);
endmodule
仿真结果如下: