这是一个摩尔状态机,具有两种状态,一种输入,一种输出。实现此状态机。请注意,重置状态为 B。
此练习与密克罗尼西亚联邦1S,但使用异步重置。
代码如下:
module top_module(
input clk,
input areset, // Asynchronous reset to state B
input in,
output out);//
parameter A=0, B=1;
reg state, next_state;
always @(*) begin // This is a combinational always block
// State transition logic状态转换逻辑块
case(state)
A: next_state = in ? A : B;
B: next_state = in ? B : A;
default: next_state = B;
endcase
end
always @(posedge clk, posedge areset) begin // This is a sequential always block
// State flip-flops with asynchronous reset异步复位触发器
if(areset)
state <= B;
else
state <= next_state;
end
// Output logic输出等价为状态B,如果当前状态为B则输出为1否则输出为0
assign out = (state == B);
endmodule
这是一个摩尔状态机,具有两种状态,一种输入,一种输出。实现此状态机。请注意,重置状态为 B。
此练习与Fsm1相似,但使用同步重置。
代码如下:
module top_module(clk, reset, in, out);
input clk;
input reset; // Synchronous reset to state B
input in;
output out;//
reg out;
// Fill in state name declarations
parameter A=0,B=1;
reg present_state, next_state;
//使用一段式状态机表示
always @(posedge clk) begin
if (reset) begin
// Fill in reset logic
present_state <= B;
out <= 1;
end else begin
case (present_state)
// Fill in state transition logic
A:next_state = in ? A : B;
B:next_state = in ? B : A;
default:next_state = B;
endcase
// State flip-flops
present_state = next_state;
case (present_state)
// Fill in output logic
A: out = 0;
B: out = 1;
default:out = 1;
endcase
end
end
endmodule
这是一个摩尔状态机,具有两个状态、两个输入和一个输出。实现此状态机。
此练习与密克罗尼西亚联邦2S,但使用异步重置。
代码如下:
module top_module(
input clk,
input areset, // Asynchronous reset to OFF
input j,
input k,
output out); //
parameter OFF=0, ON=1;
reg state, next_state;
always @(*) begin
// State transition logic
case(state)
OFF: next_state = j ? ON : OFF;
ON: next_state = k ? OFF : ON;
default:next_state = OFF;
endcase
end
always @(posedge clk, posedge areset) begin
// State flip-flops with asynchronous reset
if(areset)
state <= OFF;
else
state <= next_state;
end
// Output logic
assign out = (state == ON);
endmodule
这是一个摩尔状态机,具有两个状态、两个输入和一个输出。实现此状态机。
此练习与密克罗尼西亚联邦2,但使用同步重置。
代码如下:
module top_module(
input clk,
input reset, // Synchronous reset to OFF
input j,
input k,
output out); //
parameter OFF=0, ON=1;
reg state, next_state;
always @(*) begin
// State transition logic
case(state)
OFF: next_state = j ? ON : OFF;
ON: next_state = k ? OFF : ON;
default:next_state = OFF;
endcase
end
always @(posedge clk) begin
// State flip-flops with synchronous reset
if(reset)
state <= OFF;
else
state <= next_state;
end
// Output logic
assign out = (state == ON);
endmodule
以下是具有一个输入、一个输出和四个状态的 Moore 状态机的状态转换表。使用以下状态编码:A=2'b00、B=2'b01、C=2'b10、D=2'b11。
仅实现此状态机的状态转换逻辑和输出逻辑(组合逻辑部分)。给定当前状态 (),根据状态转换表计算 和输出 ()。statenext_stateout
代码如下:
module top_module(
input in,
input [1:0] state,
output [1:0] next_state,
output out); //
parameter A=0, B=1, C=2, D=3;
// State transition logic: next_state = f(state, in)
always@(*)begin
case(state)
A: next_state = in ? B : A;
B: next_state = in ? B : C;
C: next_state = in ? D : A;
D: next_state = in ? B : C;
default:next_state = A;
endcase
end
//没有给时钟信号所以不用写
assign out = (state == D);
// Output logic: out = f(state) for a Moore state machine
endmodule
以下是具有一个输入、一个输出和四个状态的 Moore 状态机的状态转换表。使用以下独热状态编码:A=4'b0001、B=4'b0010、C=4'b0100、D=4'b1000。
通过假设独热编码的检查来导出状态转换和输出逻辑方程。仅实现此状态机的状态转换逻辑和输出逻辑(组合逻辑部分)。(测试平台将使用非一个热输入进行测试,以确保您不会尝试做更复杂的事情)。
代码如下:
module top_module(
input in,
input [3:0] state,
output [3:0] next_state,
output out); //
parameter A=0, B=1, C=2, D=3;
// State transition logic: Derive an equation for each state flip-flop.
assign next_state[A] = state[A] & ~in | state[C] & ~in;
assign next_state[B] = state[A] & in | state[B] & in | state[D] & in;
assign next_state[C] = state[B] & ~in | state[D] & ~in;
assign next_state[D] = state[C] & in;
// Output logic:
assign out = state[D];
endmodule
以下是具有一个输入、一个输出和四个状态的 Moore 状态机的状态转换表。实现此状态机。包括将 FSM 重置为状态 A 的异步复位。
代码如下:
module top_module(
input clk,
input in,
input areset,
output out); //
parameter A = 4'b0001,B = 4'b0010,C = 4'b0100,D = 4'b1000;
reg [3:0] state,next_state;
// State transition logic
always@(*)begin
case(state)
A: next_state = in ? B : A;
B: next_state = in ? B : C;
C: next_state = in ? D : A;
D: next_state = in ? B : C;
default:next_state = A;
endcase
end
// State flip-flops with asynchronous reset
always@(posedge clk or posedge areset)begin
if(areset)
state <= A;
else
state <= next_state;
end
// Output logic
assign out = (state == D);
endmodule
以下是具有一个输入、一个输出和四个状态的 Moore 状态机的状态转换表。实现此状态机。包括将 FSM 重置为状态 A 的同步复位(这与 fsm3 的问题相同,但具有同步复位。(和上题一样,只是把异步复位改成了同步复位)
代码如下:
module top_module(
input clk,
input in,
input reset,
output out); //
parameter A = 4'b0001,B = 4'b0010,C = 4'b0100,D = 4'b1000;
reg [3:0] state,next_state;
// State transition logic
always@(*)begin
case(state)
A: next_state = in ? B : A;
B: next_state = in ? B : C;
C: next_state = in ? D : A;
D: next_state = in ? B : C;
default:next_state = A;
endcase
end
// State flip-flops with asynchronous reset
always@(posedge clk)begin
if(reset)
state <= A;
else
state <= next_state;
end
// Output logic
assign out = (state == D);
endmodule
代码如下:
module top_module (
input clk,
input reset,
input [3:1] s,
output fr3,
output fr2,
output fr1,
output dfr
);
reg [2:0] state;
reg [2:0] next;
reg ndfr;
always@(*)begin
if(reset)begin
next = 3'b111;
ndfr = 1;
end else begin
case(s)
3'b111: next = 3'b000;
3'b011: next = 3'b001;
3'b001: next = 3'b011;
3'b000: next = 3'b111;
endcase
case(s)
3'b000: ndfr = 1;
default:
ndfr = (state == next) ? dfr : ((state > next) ? 0 : 1);
endcase
end
end
always@(posedge clk)begin
state <= next;
dfr <= ndfr;
end
assign {fr3, fr2, fr1} = state;
endmodule
游戏旅鼠涉及大脑相当简单的小动物。如此简单,以至于我们将使用有限状态机对其进行建模。
在莱明斯的2D世界中,旅鼠可以处于两种状态之一:向左行走或向右行走。如果它撞到障碍物,它会改变方向。特别是,如果旅鼠在左边撞到,它会向右走。如果它在右边撞到,它会向左走。如果它同时在两侧碰撞,它仍然会改变方向。
实现具有两个状态、两个输入和一个输出的 Moore 状态机,用于模拟此行为。
代码如下:
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
output walk_left,
output walk_right); //
parameter LEFT=0, RIGHT=1;
reg state, next_state;
always @(*) begin
// State transition logic
if(state)//状态切换,如果右边有障碍物就向左走,左边有障碍物就向右走
next_state <= bump_right ? LEFT : RIGHT;
else
next_state <= bump_left ? RIGHT : LEFT;
end
always @(posedge clk, posedge areset) begin
// State flip-flops with asynchronous reset
if(areset)
state <= LEFT;
else
state <= next_state;
end
// Output logic
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
endmodule
除了左右行走之外,如果地面消失在它们下面,旅鼠还会摔倒(大概会“啊!”)。
除了左右行走并在碰撞时改变方向外,当地面=0时,旅鼠会摔倒并说“啊!当地面重新出现(地面=1)时,旅鼠将恢复以与坠落前相同的方向行走。跌倒时被撞不会影响行走方向,在与地面相同的周期内被撞到消失(但尚未下落),或者地面在仍然下落时再次出现时,也不会影响行走方向。
构建一个对此行为进行建模的有限状态机。
代码如下:
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
output walk_left,
output walk_right,
output aaah );
parameter [1:0] RIGHT = 2'd0;
parameter [1:0] LEFT = 2'd1;
parameter [1:0] L2G = 2'd2;
parameter [1:0] R2G = 2'd3;
reg [1:0] state, next_state;
wire [2:0] dirt = {ground,bump_left,bump_right};
always @(*) begin
// State transition logic
next_state = LEFT;
case(state)
LEFT:begin
if(dirt[2] == 0)
next_state = L2G;
else if((dirt == 3'b110) | (dirt == 3'b111))
next_state = RIGHT;
else
next_state = LEFT;
end
RIGHT:begin
if(dirt[2] == 0)
next_state = R2G;
else if((dirt == 3'b101) | (dirt == 3'b111))
next_state = LEFT;
else
next_state = RIGHT;
end
L2G:begin
if(dirt[2] == 1)
next_state = LEFT;
else
next_state = L2G;
end
R2G:begin
if(dirt[2] == 1)
next_state = RIGHT;
else
next_state = R2G;
end
default:next_state = LEFT;
endcase
end
always @(posedge clk, posedge areset) begin
// State flip-flops with asynchronous reset
if(areset)begin
state <= LEFT;
end
else begin
state <= next_state;
end
end
// Output logic
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
assign aaah = (state == R2G) | (state == L2G);
endmodule
除了走路和跌倒之外,旅鼠有时还可以被告知做一些有用的事情,比如挖掘(当dig=1时开始挖掘)。如果旅鼠目前在地面上行走(地面=1且未掉落),则可以挖掘,并将继续挖掘,直到到达另一侧(地面=0)。在这一点上,由于没有地面,它会掉下来(啊!),然后一旦它再次落地,继续向原来的方向走。与跌倒一样,在挖掘时被撞到没有效果,并且在跌倒或没有地面时被告知要挖洞是被忽略的。
(换句话说,行走的旅鼠可以摔倒,挖掘或改变方向。如果满足这些条件中的多个条件,则 fall 的优先级高于 dig,dig 的优先级高于切换方向的优先级。
扩展有限状态机以对此行为进行建模。
代码如下:
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
input dig,
output walk_left,
output walk_right,
output aaah,
output digging );
reg [2:0] state,next_state;
parameter left = 0,right = 1,left1 = 2,right1 = 3,dig1 = 4,dig2 = 5;
//left1表示从左边跌倒后保持住原来的方向,right1表示从右边跌倒后保持住原来的方向
//dig1表示向左边挖掘,dig2表示从右边挖掘
//组合逻辑
always @(*)
begin
case(state)
left:begin
if(ground == 1'b0)
next_state = left1;
else if(dig)
next_state = dig1;
else if(bump_left)
next_state = right;
else
next_state = left;
end
right:begin
if(ground == 1'b0)
next_state = right1;
else if(dig)
next_state = dig2;
else if(bump_right)
next_state = left;
else
next_state = right;
end
left1:begin
if(ground == 1'b0)
next_state = left1;
else
next_state = left;
end
right1:begin
if(ground == 1'b0)
next_state = right1;
else
next_state = right;
end
dig1:begin
if(ground == 1'b0)
next_state = left1;
else
next_state = dig1;
end
dig2:begin
if(ground == 1'b0)
next_state = right1;
else
next_state = dig2;
end
endcase
end
//时序逻辑
always @(posedge clk,posedge areset)
begin
if(areset)
state <= left;
else
state <= next_state;
end
//输出逻辑
assign walk_right = (state == right);
assign walk_left = (state == left);
assign aaah = (state == left1 )|(state == right1);
assign digging = (state == dig1) | (state == dig2);
endmodule
虽然旅鼠可以走路、摔倒和挖掘,但旅鼠并非无懈可击。如果旅鼠坠落太久然后撞到地面,它可能会飞溅。特别是,如果一只旅鼠坠落超过20个时钟周期,然后撞到地面,它将飞溅并停止行走,坠落或挖掘(所有4个输出变为0),永远(或直到FSM被重置)。旅鼠在落地前可以跌落多远没有上限。旅鼠只有在撞击地面时才会飞溅;它们不会在半空中飞溅。
扩展有限状态机以对此行为进行建模。
下降20个周期是可以生存的:
代码如下:
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
input dig,
output walk_left,
output walk_right,
output aaah,
output digging );
reg [2:0] state ,next_state;
parameter left = 0,right = 1,left1 = 2,right1 = 3,dig1 = 4,dig2 = 5,splat = 6,dead = 7;
reg [4:0] t ;
//left1表示从左边跌倒后保持住原来的方向,right1表示从右边跌倒后保持住原来的方向
//dig1表示向左边挖掘,dig2表示从右边挖掘,splat表示飞溅,dead表示死亡
//t表示计数
//计数器
initial
t <= 5'b1;//使用initial语句初始化
always @(posedge clk,posedge areset)
begin
if(areset)
t <= 5'b1;
else if((next_state == left1) | (next_state == right1))
t <= t+1'b1;
else
t <= 5'b1;
end
//组合逻辑
always @(*) begin
case(state)
left:begin
if(ground == 1'b0)
next_state = left1;
else if(dig)
next_state = dig1;
else if(bump_left)
next_state = right;
else
next_state = left;
end
right:begin
if(ground == 1'b0)
next_state = right1;
else if(dig)
next_state = dig2;
else if(bump_right)
next_state = left;
else
next_state = right;
end
left1:begin
if((ground == 1'b0 )&(t <= 5'd20))
next_state = left1;
else if((ground == 1'b0 )&( t>5'd20))
next_state = splat;
else
next_state = left;
end
right1:begin
if((ground == 1'b0 ) &(t <= 5'd20))
next_state = right1;
else if((ground == 1'b0 )& t>5'd20)
next_state = splat;
else
next_state = right;
end
dig1:begin
if(ground == 1'b0)
next_state = left1;
else
next_state = dig1;
end
dig2:begin
if(ground == 1'b0)
next_state = right1;
else
next_state = dig2;
end
splat:begin
if(ground == 1'b1)
next_state = dead;
else
next_state = splat;
end
dead:begin
next_state = dead;
end
endcase
end
//时序逻辑
always @(posedge clk ,posedge areset)
begin
if(areset)
state <= left;
else
state <= next_state;
end
//输出逻辑
assign walk_right = (state == right);
assign walk_left = (state == left);
assign aaah = ((state == left1 )|(state == right1)|(state == splat));
assign digging = (state == dig1) | (state == dig2);
endmodule
给定以下具有 1 个输入和 2 个输出的状态机:
假设此状态机使用独热编码,其中状态 [0] 到 state[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);
assign next_state[0] = ((|state[4:0])|(|state[9:7])) & ~in;
//当前状态为state0、1、2、3、4、7、8、9的时候,如果输入为0,那么下一状态为状态state0
assign next_state[1] = ((|state[9:8])|(state[0])) & in;
//当前状态为state0、8、9时,如果输入为1,下一状态就为state1;当同时表示多个状态时,前面加上|符号
assign next_state[2] = state[1] & in;
assign next_state[3] = state[2] & in;
assign next_state[4] = state[3] & in;
assign next_state[5] = state[4] & in;
assign next_state[6] = state[5] & in;
assign next_state[7] = (state[6]|state[7]) & in;
assign next_state[8] = state[5] & ~in;
assign next_state[9] = state[6] & ~in;
assign out1 = |state[9:8];
assign out2 = state[9] | state[7];
endmodule
PS/2 鼠标协议发送长度为三个字节的消息。但是,在连续字节流中,消息的开始和结束位置并不明显。唯一的指示是每个三个字节消息的第一个字节始终具有 bit[3]=1(但其他两个字节的 bit[3] 可能是 1 或 0,具体取决于数据)。
我们想要一个有限状态机,当给定输入字节流时,它将搜索消息边界。我们将使用的算法是丢弃字节,直到我们看到 bit[3]=1 的字节。然后,我们假设这是消息的第 1 字节,并在收到所有 3 个字节(完成)后发出接收消息的信号。
FSM 应在成功接收每条消息的第三个字节后立即在循环中发出完成信号。
代码如下:
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output done); //
parameter IDLE = 4'b0000,
BYTE1 = 4'b0001,
BYTE2 = 4'b0010,
BYTE3 = 4'b0100;
reg [3:0] state,next_state;
// State transition logic (combinational)
always@(*)begin
case(state)
IDLE:
if(in[3])
next_state <= BYTE1;
else
next_state <= state;
BYTE1:
next_state <= BYTE2;
BYTE2:
next_state <= BYTE3;
BYTE3:
if(in[3])
next_state <= BYTE1;
else
next_state <= IDLE;
endcase
end
// State flip-flops (sequential)
always@(posedge clk)begin
if(reset)
state <= IDLE;
else
state <= next_state;
end
// Output logic
assign done = (state == BYTE3);
endmodule
现在您有一个状态机来识别 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); //
// FSM from fsm_ps2
parameter IDLE = 4'b0000,
BYTE1 = 4'b0001,
BYTE2 = 4'b0010,
BYTE3 = 4'b0100;
reg [3:0] state,next_state;
// State transition logic (combinational)
always@(*)begin
case(state)
IDLE:
if(in[3])
next_state <= BYTE1;
else
next_state <= state;
BYTE1:
next_state <= BYTE2;
BYTE2:
next_state <= BYTE3;
BYTE3:
if(in[3])
next_state <= BYTE1;
else
next_state <= IDLE;
endcase
end
// State flip-flops (sequential)
always@(posedge clk)begin
if(reset)
state <= IDLE;
else
state <= next_state;
end
// Output logic
assign done = (state == BYTE3);
// New: Datapath to store incoming bytes.
always@(posedge clk)
if(reset)
out_bytes <= 24'd0;
else
out_bytes <= {out_bytes[15:0],in};
endmodule
在许多(较旧的)串行通信协议中,每个数据字节都与起始位和停止位一起发送,以帮助接收器从位流中分隔字节。一种常见的方案是使用一个起始位 (0)、8 个数据位和 1 个停止位 (1)。当没有传输任何内容(空闲)时,该线路也处于逻辑 1。
设计一个有限状态机,该状态机将在给定比特流时识别何时正确接收字节。它需要识别起始位,等待所有8个数据位,然后验证停止位是否正确。如果停止位未按预期出现,则 FSM 必须等到找到停止位后再尝试接收下一个字节。
代码如下:
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output done
);
//定义4个状态,分别为初始状态IDLE,开始接收字节状态START;
//停止接收状态STOP和等待停止信号状态WAIT
parameter IDLE = 4'b0000,
START = 4'b0001,
STOP = 4'b0010,
WAIT = 4'b0100;
//定义2个寄存器,当前状态和下一状态;再定义一个计数器
reg [3:0] state,next_state;
integer data_cnt;
//设计触发器模块
always@(posedge clk)begin
if(reset)
state <= IDLE;
else
state <= next_state;
end
//设计计数器方式模块
always@(posedge clk)begin
if(reset)
data_cnt <= 0;
else
if(state == START)
data_cnt <= data_cnt + 1;
else if(state == WAIT)
data_cnt <= data_cnt;
else
data_cnt <= 0;
end
//判断当前状态,再根据输入信号来判断下一状态
always@(*)begin
case(state)
IDLE:
if(!in)
next_state = START;
else
next_state = state;
START:
if(data_cnt == 8)
if(in)
next_state = STOP;
else
next_state = WAIT;
else
next_state = state;
STOP:
if(!in)
next_state = START;
else
next_state = IDLE;
WAIT:
if(in)
next_state = IDLE;
else
next_state = state;
default:next_state = IDLE;
endcase
end
//根据图中的信息判断出输出done就是判断当前状态是否为STOP
assign done = (state == STOP);
endmodule
现在,您有一个有限状态机,可以识别何时在串行比特流中正确接收字节,请添加一个数据路径,该路径将输出正确接收的数据字节。out_byte 在完成为 1 时需要有效,否则不在乎。
请注意,串行协议首先发送最低有效位。
代码如下:
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
);
// Use FSM from Fsm_serial
//定义4个状态,分别为初始状态IDLE,开始接收字节状态START;
//停止接收状态STOP和等待停止信号状态WAIT
parameter IDLE = 4'b0000,
START = 4'b0001,
STOP = 4'b0010,
WAIT = 4'b0100;
//定义2个寄存器,当前状态和下一状态;再定义一个计数器
reg [3:0] state,next_state;
integer data_cnt;
//设计触发器模块
always@(posedge clk)begin
if(reset)
state <= IDLE;
else
state <= next_state;
end
//设计计数器方式模块
always@(posedge clk)begin
if(reset)
data_cnt <= 0;
else
if(state == START)
data_cnt <= data_cnt + 1;
else if(state == WAIT)
data_cnt <= data_cnt;
else
data_cnt <= 0;
end
//判断当前状态,再根据输入信号来判断下一状态
always@(*)begin
case(state)
IDLE:
if(!in)
next_state = START;
else
next_state = state;
START:
if(data_cnt == 8)
if(in)
next_state = STOP;
else
next_state = WAIT;
else
next_state = state;
STOP:
if(!in)
next_state = START;
else
next_state = IDLE;
WAIT:
if(in)
next_state = IDLE;
else
next_state = state;
default:next_state = IDLE;
endcase
end
//根据图中的信息判断出输出done就是判断当前状态是否为STOP
assign done = (state == STOP);
// New: Datapath to latch input bits.
always@(posedge clk)begin
if(reset)
out_byte <= 8'b0;
else if(state == START && data_cnt < 8)
out_byte[data_cnt] <= in;
else
out_byte <= out_byte;
end
endmodule
我们希望为串行接收器添加奇偶校验。奇偶校验在每个数据字节后添加一个额外的位。我们将使用奇偶校验,其中收到的 9 位中的 1秒数必须是奇数。例如,101001011满足奇奇偶校验(有 5 个 1s),但001001011不满足。
更改 FSM 和数据路径以执行奇偶校验。仅当正确接收字节且其奇偶校验通过时,才断言 done 信号。像串行接收器 FSM,此FSM需要识别起始位,等待所有9(数据和奇偶校验)位,然后验证停止位是否正确。如果停止位未按预期出现,则 FSM 必须等到找到停止位后再尝试接收下一个字节。
为您提供了以下模块,可用于计算输入流的奇偶校验(这是重置的 TFF)。预期用途是应为其提供输入位流,并在适当的时间重置,以便计算每个字节中的 1 位数。
提示:
module parity (
input clk,
input reset,
input in,
output reg odd);
always @(posedge clk)
if (reset) odd <= 0;
else if (in) odd <= ~odd;
endmodule
请注意,串行协议首先发送最低有效位,在 8 个数据位之后发送奇偶校验位。
代码如下:
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
); //
// Modify FSM and datapath from Fsm_serialdata
//定义4个状态,分别为初始状态IDLE,开始接收字节状态START;
//停止接收状态STOP和等待停止信号状态WAIT
parameter IDLE = 4'b0000,
START = 4'b0001,
STOP = 4'b0010,
WAIT = 4'b0100;
//定义2个寄存器,当前状态和下一状态;再定义一个计数器
reg [3:0] state,next_state;
integer data_cnt;
wire odd;
//设计触发器模块
always@(posedge clk)begin
if(reset)
state <= IDLE;
else
state <= next_state;
end
//设计计数器方式模块
always@(posedge clk)begin
if(reset)
data_cnt <= 0;
else
if(state == START)
data_cnt <= data_cnt + 1;
else if(state == WAIT)
data_cnt <= data_cnt;
else
data_cnt <= 0;
end
//判断当前状态,再根据输入信号来判断下一状态
always@(*)begin
case(state)
IDLE:
if(!in)
next_state = START;
else
next_state = state;
START:
if(data_cnt == 9)//加1位奇偶校验位
if(in)
if(odd)//判断最后1位是否为1
next_state = STOP;
else
next_state = IDLE;
else
next_state = WAIT;
else
next_state = state;
STOP:
if(!in)
next_state = START;
else
next_state = IDLE;
WAIT:
if(in)
next_state = IDLE;
else
next_state = state;
default:next_state = IDLE;
endcase
end
//根据图中的信息判断出输出done就是判断当前状态是否为STOP
assign done = (state == STOP);
// New: Datapath to latch input bits.
always@(posedge clk)begin
if(reset)
out_byte <= 8'b0;
else if(state == START && data_cnt < 8)
out_byte[data_cnt] <= in;
else
out_byte <= out_byte;
end
// New: Add parity checking.
parity parity_inst(clk,(state != START),in,odd);
endmodule
同步 HDLC 成帧涉及解码连续的比特数据流,以查找指示帧(数据包)开始和结束的位模式。正好看到 6 个连续的 1(即 01111110)是一个指示帧边界的“标志”。为了避免数据流意外包含“标志”,发送方在每 5 个连续 1 后插入一个零,接收方必须检测并丢弃该零。如果有 7 个或更多连续的 1,我们还需要发出错误信号。
创建一个有限状态机来识别这三个序列:
0111110:信号位需要丢弃(光盘)。
01111110:标记框架的开头/结尾(标志)。
01111111...:错误(7 个或更多 1)(错误)。
重置 FSM 时,它应处于与先前输入为 0 的行为状态。
下面是一些说明所需操作的示例序列。
代码如下:
module top_module(
input clk,
input reset, // Synchronous reset
input in,
output disc,
output flag,
output err);
//6 个连续的 1(即 01111110)是一个指示帧边界的“标志”。
//先定义状态
parameter IDLE = 4'b0000,
ONE = 4'b0001,//1
TWO = 4'b0010,//11
THREE = 4'b0011,//111
FOUR = 4'b0100,//1111
FIVE = 4'b0101,//11111
SIX = 4'b0110,//111111
DISC = 4'b0111,//111110
FLAG = 4'b1000,//1111110
ERROR = 4'b1001;//1111111...
reg [3:0]state,next_state;
always@(posedge clk)
if(reset)
state <= IDLE;
else
state <= next_state;
always@(*)
case(state)
IDLE: next_state = in ? ONE : IDLE;
ONE: next_state = in ? TWO : IDLE;
TWO: next_state = in ? THREE : IDLE;
THREE: next_state = in ? FOUR : IDLE;
FOUR: next_state = in ? FIVE : IDLE;
FIVE: next_state = in ? SIX : DISC;
SIX: next_state = in ? ERROR : FLAG;
DISC: next_state = in ? ONE : IDLE;
FLAG: next_state = in ? ONE : IDLE;
ERROR: next_state = in ? ERROR : IDLE;
default:state = IDLE;
endcase
assign disc = (state == DISC);
assign flag = (state == FLAG);
assign err = (state == ERROR);
endmodule