转载自:知乎
作者:ljgibbs首先附上传送门:Exams/m2014 q6c - HDLBits首先附上传送门:
Exams/m2014 q6c - HDLBitshdlbits.01xz.net
Problem 145 Q6c FSM one-hot next-state logic
牛刀小试
本题和前一题的状态转移图相同,但使用独热码来为状态机编码。
状态机编码
状态机编码主要可以分为独热码(one-hot code) 编码以及二进制编码两类。
独热码为每个状态分配 1 个比特位,该位为 1'b1 置起时表示状态机处于该状态。使用独热码的好处在于状态判断时不需要组合逻辑,判断对应状态的触发器输出即可。
举个栗子,state = 3'b1 表示状态 A, 3'b2 表示状态 B,3'b4 表示状态 C ,使用独热码编码。判断是否为状态 A 时,只需要判断 state[0] 是否为 1'b1; 状态 B C 同理。
如果使用二进制码编码,好处在于更少的触发器。只需要使用 2 个触发器,即 2 bit 就可以表示 3 个状态。但判断状态 A 时需要使用组合逻辑 ~state[1] && state[0] 。组合逻辑会增加时序路径长度,降低系统最大工作频率。
所以在触发器资源较为丰富的 FPGA 应用中一般使用独热码而不是二进制来对状态编码。
言归正传,本题使用 6 bit 来表示 6 个状态,为 000001 表示状态 A,000010 表示状态 B,等等依次类推。
和上一题一样,本题要求输出次状态 nxt\_state 的一部分即 Y2,Y4.
注意:在这道练习中,为了判断读者是否使用独热码来编码,以及使用独热码的方式来处理状态跳变。本题 testbench 会输入一些不存在的状态。如果使用二进制编码,这些不存在的状态都会使状态机跳转到 default 分支,从而引发输出错误(尽管逻辑正确)。
使用独热码,因为是分别对每一 bit 进行状态跳转判断,所以每一比特仍然会分别进入正常状态的分支。(但其实此时状态是错误的,本题如此设置是出于考察独热码的使用。)
比如输入一个不存在的状态 6'b000011,二进制编码时进入 default 分支,状态固定为复位状态。但独热码应用中,最低位和次低位同时为 1,分别判断为状态 A 或是状态 B,进行跳转。testbench 会分别检查这些跳转。
解答与分析
module top_module (
input [6:1] y,
input w,
output Y2,
output Y4);
`define STT_W 6
`define STT_W1 `STT_W - 1
wire [`STT_W1:0] state = y;
reg [`STT_W1:0] nxt_state;
localparam sA = `STT_W'd1;
localparam sB = `STT_W'd2;
localparam sC = `STT_W'd4;
localparam sD = `STT_W'd8;
localparam sE = `STT_W'd10;
localparam sF = `STT_W'd20;
// State transition logic (combinational)
always @(*) begin
nxt_state[0] <= w ? state[0] || state[3] : 1'b0;
nxt_state[1] <= w ? 1'b0 : state[0];
nxt_state[2] <= w ? 1'b0 : state[5] || state[1];
nxt_state[3] <= w ? state[1] || state[2] || state[4] || state[5]: 1'b0;
nxt_state[4] <= w ? 1'b0 : state[4] || state[2];
nxt_state[5] <= w ? 1'b0 : state[3];
end
assign Y2 = nxt_state[1];
assign Y4 = nxt_state[3];
endmodule
根据题意输出次状态的一部分 Y2 Y4,由于输入的是 y[6:1] ,所以 Y2 对应于解答中的 nxt\_state[1],Y4 同理。
Problem 146 Q6 FSM
牛刀小试
本题的状态转移图和上一题相同,但此题需要实现一个完整的状态机,并根据图中的标识产生正确的输出 z 。
解答与分析
module top_module (
input clk,
input reset, // synchronous reset
input w,
output z);
`define STT_W 6
`define STT_W1 `STT_W - 1
reg [`STT_W1:0] state;
reg [`STT_W1:0] nxt_state;
localparam sA = `STT_W'd1;
localparam sB = `STT_W'd2;
localparam sC = `STT_W'd4;
localparam sD = `STT_W'd8;
localparam sE = `STT_W'd10;
localparam sF = `STT_W'd20;
// State transition logic (combinational)
always @(*) begin
nxt_state[0] <= w ? state[0] || state[3] : 1'b0;
nxt_state[1] <= w ? 1'b0 : state[0];
nxt_state[2] <= w ? 1'b0 : state[5] || state[1];
nxt_state[3] <= w ? state[1] || state[2] || state[4] || state[5]: 1'b0;
nxt_state[4] <= w ? 1'b0 : state[4] || state[2];
nxt_state[5] <= w ? 1'b0 : state[3];
end
always @(posedge clk ) begin
if(reset)
state <= sA;
else begin
state <= nxt_state;
end
end
assign z = state[4] || state[5];
endmodule
Problem 147 Q2a FSM
牛刀小试
本题仍然似乎是一道原作者任教学校的测试题。编写 Verilog 代码实现下图中的状态机。这道测试题要求分别使用两个 always 块来实现状态跳转以及状态触发器逻辑。输出逻辑可以使用 assign 连续赋值也可以使用 always 块实现,随你的便。状态编码方式也随你的便。
但请 注意 这里的图和上题中的状态转移图有所 不同 !
(来自一个一开始没发现的人。。。)
注意这里的图和上题中的图不同
解答与分析
逻辑和上一题没有不同,不再赘述代码,注意根据状态转移图实现正确的状态转移逻辑。
Problem 148 Q2b One-hot FSM equations
牛刀小试
本题和此前的题目类似,使用独热码编码方式来描述上题中的状态机。如果在此前的题目中搭建了完善的状态机框架,那么稍稍修改就能够应对此题。这里就不再赘述了。
Problem 149 Q2a FSM (Exams/2013 q2afsm)
牛刀小试
本题需要实现一个如下图的状态机。
本状态机扮演一个仲裁电路,控制三个设备对于某种资源的访问权限。
每个设备通过置起 r[i] 信号为 1'b1 来表示对这种资源的请求。r[1],r[2].r[3]分别对应三个设备的请求信号。三个请求信号作为 FSM 的输入信号。
FSM 在没有任何请求时处于状态 A。当出现了一个或多项请求时,由 FSM 决定哪台设备获得资源的,并向其发出许可信号 g[i],置为 1'b1。g[i] 信号是 FSM 的输出信号。
本系统存在优先级,设备 1 拥有最高权限,设备 2 次之,设备 3 的权限最低。因此设备 3 只能在系统处于状态 A 的情况下才能获得资源访问权限。一旦设备获得 FSM 给出的许可信号后,将持续持有资源直至其将请求信号置低为止,请求信号为高期间不能被打断。
编写 Verilog 代码实现这个 FSM。分别使用两个 always 块来实现状态跳转以及状态触发器逻辑。输出逻辑可以使用 assign 连续赋值也可以使用 always 块实现,随你的便。状态编码方式也随你的便。
解答与分析
module top_module (
input clk,
input resetn, // active-low synchronous reset
input [3:1] r, // request
output [3:1] g // grant
);
`define STT_W 4
`define STT_W1 `STT_W - 1
wire [2:0] ri = r;
wire [2:0] go;
reg [`STT_W1:0] state;
reg [`STT_W1:0] nxt_state;
localparam sidle = 0;
localparam sd1 = 1;//devive 1
localparam sd2 = 2;
localparam sd3 = 3;
// State transition logic (combinational)
always @(*) begin
nxt_state[sidle] <= (state[sidle] && ~(|ri))
|| (state[sd1] && ~ri[0])
|| (state[sd2] && ~ri[1])
|| (state[sd3] && ~ri[2]);
nxt_state[sd1 ] <= (state[sidle] && ri[0])
|| (state[sd1 ] && ri[0]);
nxt_state[sd2 ] <= (state[sidle] && ~ri[0] && ri[1])
|| (state[sd2 ] && ri[1]);
nxt_state[sd3 ] <= (state[sidle] && ~ri[0] && ~ri[1] && ri[2])
|| (state[sd3 ] && ri[2]);
end
// State flip-flops (sequential)
always @(posedge clk ) begin
if(~resetn)
state <= `STT_W'b1;
else begin
state <= nxt_state;
end
end
//output logic
assign go[0] = state[sd1 ];
assign go[1] = state[sd2 ];
assign go[2] = state[sd3 ];
assign g = go;
endmodule
若从题目所给的状态转移图来描述这个状态机是比较容易的。我们可以从中学习使用状态机实现一个优先级系统的思路。最好能够不依赖于状态转移图,根据请求与许可信号来描述这个 FSM 系统。
推荐阅读
- HDLBits:在线学习 Verilog (二十九 · Problem 140-144)
- HDLBits:在线学习 Verilog (二十八 · Problem 135-139)
- HDLBits:在线学习 Verilog (二十七 · Problem 130-134)
- HDLBits: 在线学习Verilog(Problem 127-130)
- HDLBits:在线学习 Verilog (二十四 · Problem 115-119)
关注此系列,请关注专栏FPGA的逻辑