6.3 同步时序逻辑电路的设计
目标:根据逻辑功能要求,设计逻辑电路图。
同步时序逻辑设计的一般步骤:
例:用D触发器设计一个8421BCD码同步十进制加计数器
分析:实质上是对时钟脉冲计数0, 1, 2, ..., 9, 0, 1, 2, ...
列出状态表,分配状态
4位编码对应16种状态,本例只取其中10个为有效状态,其余为无效状态。
选择触发器
每位Q对应一个D触发器,四位对应四个D触发器。特性方程: \(Q^{n+1}=D\)
确定方程组
\( Q_{3}^{n+1}=D_3=Q_{3}^{n}\overline{Q_{0}^{n}}+Q_{2}^{n}Q_{1}^{n}Q_{0}^{n} \)
\( Q_{2}^{n+1}=D_2=Q_{2}^{n}\overline{Q_{1}^{n}}+Q_{2}^{n}\overline{Q_{0}^{n}}+\overline{Q_{2}^{n}}Q_{1}^{n}Q_{0}^{n} \)
\( Q_{1}^{n+1}=D_1=Q_{1}^{n}\overline{Q_{0}^{n}}+\overline{Q_{3}^{n}Q_{1}^{n}}Q_{0}^{n} \), \( Q_{0}^{n+1}=D_0=\overline{Q_{0}^{n}} \)
绘制逻辑电路图(略)
检查自启动能力
将6个无效状态代入电路没有简化之前的方程组,求次态
按照该方程组得到的电路具备自启动/自校正能力。
例:设计一"011"序列检测器,每当X输入011码时,电路输出Y为1
输入端X:串行随机信号
输出端Y:当X出现011序列时,Y=1;否则Y=0
状态图的建立:
状态A:开始检测/重新检测
状态B:表示已经收到了"0"
状态C:已经连续输入"01"
状态D:已经连续输入"011"
Verilog建模
明确输入:时钟CP、被检信号X、复位rst
输出:Y
对状态进行编码
module SequenceDetector011( input cp, input rst, input x, output y ); parameter STATE_A = 4'b0001; parameter STATE_B = 4'b0010; parameter STATE_C = 4'b0100; parameter STATE_D = 4'b1000; reg [3:0] state; always @(posedge cp or posedge rst) begin if (rst) begin state <= STATE_A; end else begin case (state) STATE_A: if (!x) state <= STATE_B; STATE_B: if (x) state <= STATE_C; STATE_C: if (x) state <= STATE_D; else state <= STATE_B; STATE_D: if (x) state <= STATE_A; else state <= STATE_B; default: state <= STATE_A; endcase end end assign y = (state == STATE_D); endmodule // SequenceDetector011
有限状态机的设计 时序逻辑电路就是和“状态”打交道。状态机的本质就是对具有逻辑顺序或时序规律的事件的一种描述方法。状态机的工作方式是控制信号根据预先设定的状态“顺序”运行的,它是纯硬件系统中的顺序控制电路。通常采用case语句设计实现。
根据功能要求,设计出状态图
明确状态的转换关系并注明状态转换条件注明输出与状态、输入的关系
对状态进行编码
二进制编码、格雷编码、独热码
分段设计状态机主体
第一段:采用always模块描述状态转移条件和规律
第二段:采用always或assign模块或组合逻辑描述输出
检查是否有自启动能力
检查状态变量是否有初始值和默认值
always复位语句中赋初值
case分支语句中,要有default语句,将其它无效状态转到有效状态
售货机设计
售货机能自动识别1元和0.5元的硬币,出货口和找零口,矿泉水的价格是1.5元。
已知关系:当投入的金额等于1.5元时,出货口输出一瓶矿泉水;当投入的金额大于1.5元时(即2元,不会超过2元),出货口输出一瓶矿泉水,同时找零口输出相应余额的硬币。
明确输入输出:
输入:按键BTN、投币M(2bit,01表示0.5元,10表示1元)
隐性输入:clk、rst
输出:出水W、退钱:Y(2bit,01表示0.5元,10表示1元)
画状态图
二进制编码:
parameter STATE_A = 4'b00; parameter STATE_B = 4'b01; parameter STATE_C = 4'b10; parameter STATE_D = 4'b11;
独热码:
parameter STATE_A = 4'b0001; parameter STATE_B = 4'b0010; parameter STATE_C = 4'b0100; parameter STATE_D = 4'b1000;
`default_nettype none module FiniteStateMachineSeller( clk, rst, inMoney, btnCancel, water, outMoney ); input wire clk; input wire rst; input wire [1:0] inMoney; // 01---$0.5, 10---$1.0 input wire btnCancel; // Out Money output wire water; // Out Water output wire [1:0] outMoney; // 01---$0.5, 10---$1.0 parameter ZERO = 7'b0000001; // Waiting... parameter HALF = 7'b0000010; // Get $0.5 parameter ONE = 7'b0000100; // Get $1.0 parameter ONE_AND_HALF = 7'b0001000; // Get $1.5 parameter TWO = 7'b0010000; // Get $2.0 parameter OUT_HALF = 7'b0100000; // Out $0.5 parameter OUT_ONE = 7'b1000000; // Out $1.0 reg [6:0] state; always @(posedge clk) begin if (rst) begin state <= ZERO; end else begin case (state) ZERO: if (inMoney == 2'b01) state <= HALF; else if (inMoney == 2'b10) state <= ONE; HALF: if (inMoney == 2'b01) state <= ONE; else if (inMoney == 2'b10) state <= ONE_AND_HALF; else if (btnCancel) state <= OUT_HALF; ONE: if (inMoney == 2'b01) state <= ONE_AND_HALF; else if (inMoney == 2'b10) state <= TWO; else if (btnCancel) state <= OUT_ONE; ONE_AND_HALF: state <= ZERO; TWO: state <= OUT_HALF; OUT_HALF: state <= ZERO; OUT_ONE: state <= ZERO; default: state <= ZERO; endcase end end assign water = (state == TWO) | (state == ONE_AND_HALF); assign outMoney = (state == OUT_ONE) ? 2'b10 : (state == OUT_HALF) ? 2'b01 : 2'b00; endmodule // FiniteStateMachineSeller