Chapter4

引言

时序逻辑电路定义

  • 时序逻辑电路的输出由当前时刻的输入和之前时刻的输入共同决定;
  • 时序逻辑电路内部具有记忆;
  • 一些基本概念
    • 状态:用于解释电路未来行为所需的信息;
    • 锁存器与触发器:用于存储1比特状态的模块;
    • 同步时序逻辑电路:一类由组合逻辑和一组表示电路状态的触发器所构成的电路。

时序逻辑电路特征

  • 按照一定的输入输出时序实现功能;
  • 电路内部具有短期记忆;
  • 在输出与输入之间具有反馈回路。

1

锁存器和触发器

电路中的状态

  • 电路中的状态会影响电路未来的行为;
  • 一些常见的电路状态存储模块
    • 双稳态电路;
    • SR锁存器;
    • D锁存器;
    • D触发器。

双稳态电路

定义

  • 双稳态电路是其他存储模块的基础;
  • 下图两个电路具有以下特点:
    • 对称性;
    • 有两个输出:Q和Q
    • 没有输入。

2

分析

3

4

  • 由以上分析可以看到,电路存在两种状态,用0和1表示,可以用这两种状态存储1比特二进制状态;
  • 但该电路中没有输入端,无法控制电路中状态的存储。

SR锁存器(Latch)

定义

  • SR锁存器
    • 两个输入端(激励信号);
    • 两个输出端(状态)。
  • 考虑以下四种输入情况
    • S=1,R=0;
    • S=0,R=1;
    • S=0,R=0;
    • S=1,R=1。

5

分析

6

7

8

总结

  • SR锁存器是一个存储1比特状态的双稳态模块
    • SR分别表示置位(Set)和复位(Reset)
  • 通过控制S、R信号的输入,控制锁存器的状态
    • Set置位,使Q=1(S=1,R=0);
    • Reset复位,使Q=0(S=0,R=1);
    • 保持,使Qn+1=Qn(S=0,R=0);
    • 禁止输入,S=R=1。

9

D锁存器

定义

  • 包含两个输入端:CLK,D
    • CLK:控制锁存器状态发生改变的时间;
    • D:数据输入,控制下一个状态的值。
  • 功能
    • 当CLK=1时,Qn=D,Q跟随D进行变化,D锁存器是透明的;
    • 当CLK=0时,Qn+1=Qn,Q保持原先的状态,D锁存器是不透明的。
  • D锁存器避免了SR锁存器中S和R信号同时有效而造成的奇怪情况。

10

实现

11

12

D触发器(Flip-flop)

定义

  • 包含两个输入端:CLK,D
  • 功能
    • 在CLK的上升沿对D进行采样
      • 当CLK的信号从0到1的瞬间,Q被修改为当前时刻D的值;
      • 在其他时刻,Q处于保持状态。
    • Q的值只会在CLK的上升沿时刻发生改变
  • 这种工作模式被称为边沿触发。

13

主从式D触发器的实现

  • 由两个顺序连接的D锁存器构成(L1,L2);
  • 由一组相反的时钟信号所控制。

14

  • 当CLK=0时
    • 主锁存器L1是透明的;
    • 从锁存器L2是不透明的;
    • 主锁存器的状态(N1)跟随D变化。
  • 当CLK=1时
    • 主锁存器L1是不透明的;
    • 从锁存器L2是透明的;
    • 从锁存器的状态跟随N1变化。
  • 因此在时钟的上升沿时刻(CLK 0→1)
    • Q被赋值为D。

带使能端的D触发器

  • 三个输入端:CLK,D,EN
    • EN为使能端:用来控制D是否能被触发器存储
  • 功能(EN信号高电平有效)
    • EN=1:在时钟上升沿时,Q被更新为当前时刻的D值;
    • EN=0:触发器处于保持状态。

17

带复位功能的D触发器

  • 三个输入端:CLK,D,Reset
  • 功能(Reset信号高电平有效)
    • Reset=1:Q被强制设置为0;
    • Reset=0:触发器正常工作。
  • 同步复位
    • 只在CLK上升沿进行复位。
  • 异步复位
    • 只要Reset信号有效即可复位。

18

带置位功能的D触发器

  • 三个输入端:CLK,D,Set
  • 功能(Set信号高电平有效)
    • Set=1:Q被强制设置为1;
    • Set=0:触发器正常工作。

19

D锁存器与D触发器

15

寄存器(Register)

  • 一个N位寄存器由一个共享的CLK输入和N个D触发器组成;
  • 寄存器的所有位同时被更新;
  • 是大多数时序电路中的关键组件。

16

同步逻辑设计

时序逻辑电路

  • 时序逻辑电路:所有不是组合逻辑的电路
    • 电路的输出不能简单地通过观察当前输入来决定。
  • 一个有问题的电路
    • 没有输入;
    • 有1-3个输出。

20

非稳态电路

  • 电路特征
    • 非稳态电路;
    • 输出结果周期性地翻转;
    • 电路中具有回路,输出端反馈至输入端。
  • 环形振荡器

21

22

同步时序电路

定义

  • 在信号传播路径中插入寄存器以断开电路中环路
    • 使电路转变成组合逻辑电路和寄存器的集合。
  • 寄存器包含系统的状态;
  • 状态仅在始终边沿(上升沿或下降沿)到达时发生改变
    • 即状态同步与时钟信号。
  • 如果时钟足够慢,使得在下一个时钟沿到达之前,输入寄存器的信号都可以稳定下来,则所有的冒险将被消除;
  • 一个时序电路包含一组有限的离散状态(S0,S1,S2…Sk-1);
  • 同步时序电路有一个时钟输入;
  • 上升沿表示电路状态转变发生的时间
    • 当前状态(现态):当前系统的状态;
    • 下一个状态(次态):下一个时钟沿后系统将进入的状态。
  • 功能规范:
    • 描述当前状态和输入的各种组合所对应的下一个状态和输出。
  • 时序规范:
    • 建立时间、保持时间。

组成规则

  • 组成规则:
    • 电路中的模块或者是寄存器或者是组合逻辑电路;
    • 模块中至少包含一个寄存器;
    • 所有的寄存器都共用一个时钟信号;
    • 电路的每个环路至少包含一个寄存器。
  • 两类常见的同步时序逻辑电路
    • 有限状态机(FSM);
    • 流水线。

一个简单的同步时序电路实例

23

  • 一个D触发器是一个最简单的同步时序电路
    • 包含一个输入D;
    • 一个时钟CLK;
    • 一个输出Q;
    • 两个状态(0,1)。
  • D触发器功能规范
    • 下一个状态是D;
    • 输出Q是当前状态。

思考:下列那些电路是同步时序电路?

24

  1. F,模块可以是组合逻辑电路,但模块中必须包含一个寄存器;
  2. T,电路中的模块或者是寄存器或者是组合逻辑电路,寄存器又是由触发器组成;
  3. F,图中为锁存器;
  4. T,电路的每个环路至少包含一个寄存器;
  5. T;
  6. F,电路的每个环路至少包含一个寄存器;
    • 如果三个CLK相同,T,所有的寄存器都共用一个时钟信号;
    • 反之,F。

异步时序电路

  • 非同步的时序电路称为异步时序电路;
  • 理论上,异步时序电路设计比同步时序电路更通用
    • 系统的时序不由时钟控制的寄存器所约束。
  • 实际上,几乎所有的系统本质上都是同步的
    • 同步时序电路比异步时序电路更容易设计。

有限状态机

有限状态机结构

由以下模块组成

  • 状态寄存器
    • 存储当前时刻的状态;
    • 状态在下一个有效时钟沿发生改变。
  • 组合逻辑
    • 计算下一个状态;
    • 计算电路的输出。

25

Moore和Mealy型有限状态机

  • 次态由现态和当前输入共同决定;
  • 根据输出逻辑的不同,可以将有限状态机分为两类
    • Moore型:输出仅由当前时刻状态所决定;
    • Mealy型:输出由当前时刻状态和输入共同决定。

26

例:交通灯控制器

设计

  • 输入:两个交通传感器TA和TB
    • 当路上有人出现时,传感器返回TRUE;
    • 否则返回FALSE。
  • 输出:两个交通灯LA和LB
    • 红色、黄色和绿色。
  • 周期为5s的时钟,在每一个时钟沿到达时,灯根据交通传感器来改变;
  • 一个复位按键,可以使交通灯控制器回到初始状态。

27

有限状态机黑盒视图

  • 输入:CLK,Reset,TA,TB
  • 输出:LA,LB

28

状态转换图

29

  • 图中的每一个圆圈代表一个状态;
  • 图中的每一个圆弧代表两个状态之间的转换;
  • 圆弧上的项表示实现状态转换所需要的输入;
  • 状态转换发生在时钟有效沿产生的时刻;
  • Moore型状态机:输出信息标在状态(圆圈)中。

状态转换表

30

对状态进行编码

31

输出表

32

原理图:寄存器

33

原理图:次态逻辑

34

原理图:输出逻辑

35

时序图

36

Moore型有限状态机设计方法

  1. 根据问题进行抽象,确定输入输出以及对应的逻辑含义;
  2. 画出状态转换图;
  3. 列出状态转换表;
  4. 对状态进行编码,并列出次态方程;
  5. 列出输出表;
  6. 对输出进行编码,并列出输出方程;
  7. 绘制原理图。

状态编码

定义

  • 不同的状态编码和输出编码会产生不同的电路;
  • 进行合理的编码,使之能产生一个逻辑门数最少且传播延迟最短的电路;
  • 目前没有一种简单的办法可以找到;
  • 可以通过计算机辅助设计(CAD)工具来解决;
  • 常见的状态编码有两种
    • 二进制编码(Binary encoding);
    • 独热编码(One-hot encoding);
    • 可以理解为译码器的输入与输出端的形式。

二进制编码

例如:4种状态,对应的编码为:00,01,10,11。

独热编码

  • 状态的每一位(1 bit)表示一种状态;
  • 任何时候只能有一位是“热的”(TRUE或1);
  • 例如:4种状态,对应的编码为:0001,0010,0100,1000;
  • 需要使用更多的触发器;
  • 相比于二进制编码,次态逻辑和输出逻辑实现起来更加的简单。

Moore型状态机 VS Mealy状态机

实例

37

状态转换图

38

Moore型状态机的状态转换表

39

Moore型状态机的输出表

40

Mealy型状态机状态转换表和输出表

41

Moore型状态机原理图

42

Mealy型状态机原理图

43

Moore型和Mealy型状态机时序图

44

Mealy型有限状态机设计方法

  1. 根据问题进行抽象,确定输入输出以及对应的逻辑含义;
  2. 画出状态转换图;
  3. 列出状态转换表和输出表(可同时列出);
  4. 对状态和输出进行编码,并列出次态方程和输出方程;
  5. 绘制原理图。

Moore型状态机与Mealy型状态机的总结

Moore型状态机:输出只和现态有关

  • 在状态转换图中,输出标记在圆圈内;
  • 输入后,需要等待状态的变化才能得到输出;
  • 相同情况下需要使用更多的状态。

Mealy型状态机:输出与现态和输入都有关

  • 在状态转换图中,输出标记在圆弧上;
  • 输出可以直接响应输入;
  • 相同情况下需要使用更少的状态。

状态机的分解

目标

将复杂的有限状态机分解成多个简单的状态机

  • 其中一些状态机的输出是另一些状态机的输入;
  • 层次化、模块化。

实例

为交通灯控制器增加“游行”模式

  • 增加两个输入端:P,R;
  • 当P=1时,进入“游行”模式,保证Bravado Blvd.大道的交通灯一直为绿色;
  • 当R=1时,退出“游行”模式。

45

“游行”模式状态机设计

46

未分解的状态转换图

47

分解后的状态转换图

raw

有限状态机设计小结

  1. 确定输入和输出;
  2. 画状态转换图;
  3. 对于Moore型状态机
    • 写出状态转换表;
    • 写出输出表。
  4. 对于Mealy型状态机
    • 写出组合的状态转换表和输出表。
  5. 选择状态编码;
  6. 写出次态方程和输出方程;
  7. 绘制电路原理图。

由电路图导出状态机

主要步骤

  • 电路分析:在给定电路原理图的情况下推断电路的逻辑功能,是电路设计的逆过程
    • 当承担一个没有完整文档的项目;
    • 开展基于其他人系统的逆向工程。
  • 主要步骤
    1. 检查电路,表明输入输出和状态位;
    2. 写出次态方程和输出方程;
    3. 列出状态表和输出表;
    4. 删除不可达状态以简化状态表;
    5. 给每个有效状态编码指定状态名称;
    6. 用状态名称重写状态表和输出表;
    7. 画出状态转换图;
    8. 使用文字描述有限状态机的功能。

实例:键盘锁电路分析

下图是一个键盘锁电路,包含两个输入和一个输出,当输出为1时表示开锁成功。试分析,如何进行输入才能使电路产生开锁信号。

49

步骤

50

51

52

53

54

55

56

57

58

59

时序逻辑中的时序问题

时序

  • D触发器在时钟有效边沿(上升沿/下降沿)对输入D采样,并复制给Q;
  • 在采样的时刻,D必须处在一个稳定的状态,为0或为1;
  • 这个过程如同照相一样
    • 只有当被拍摄物体静止不动时才能获得清晰的图像。
  • 如果在采样时刻,D未处于稳定的状态,则会产生亚稳态。

输入时序约束

  • 建立时间(Setup time):tsetup=在时钟有效边沿到来前输入信号所需要的稳定时间;
  • 保持时间(Hold time):thold=在时钟有效边沿到来后输入信号所保持稳定的时间;
  • 孔径时间(Aperture time):ta=在时钟边沿附近输入信号需要保持稳定的总时间;
  • ta=tsetup+thold

60

输出时序约束

  • 传播延迟(Propagation delay):tpcq=时钟有效边沿到达后到Q最终稳定所需的最长时间;
  • 最小延迟(Contamination delay):tccq=时钟有效边沿到达后到Q开始改变所需的最短时间。

61

动态约束

  • 同步时序电路中,输入必须在时钟有效边沿附近的孔径时间内保持稳定;
  • 输入信号必须稳定
    • 在时钟有效边沿到达前,至少稳定tsetup
    • 在时钟有效边沿到达后,至少稳定thold

62

系统时序

  • 时钟周期Tc是两个时钟上升沿(或下降沿)之间的间隔;
  • fc=1/Tc,表示时钟频率;
  • 提高时钟频率可以增加数字系统在单位时间内完成的工作量,但频率不能无限制的增加。

63

  • 如上图所示,两个寄存器间的延迟具有最小和最大延迟;
  • 这些延迟是由其中的电路元件的延迟所决定。

建立时间约束

65

  • 建立时间约束由路径R1至R2间的最大延迟所决定
    • 寄存器的传播延迟tpcq
    • 组合逻辑电路的传播延迟tpd
  • 寄存器R2的输入信号必须在下一个时钟上升沿的tsetup时间前稳定。

64

  • tpd≤Tc-(tpcq+tsetup)
  • 上式被称为建立时间约束或最大延迟约束;
  • 限制了通过组合逻辑的最大延迟;
  • 在商业设计中
    • Tc由研发总监和市场部提出,以确保产品的竞争性;
    • 制造商确定触发器的传播延迟tpcq和建立时间tpcq
    • tpcq+tpcq被称为时序开销,由芯片的生产工艺所决定;
    • 通常,只有tpd是设计人员能够控制的变量。

保持时间约束

66

  • 保持时间约束由路径R1至R2间的最短延迟所决定
    • 寄存器的最小延迟tccq
    • 组合逻辑电路的最小延迟tcd
  • 寄存器R2的输入信号必须在时钟上升沿后至少稳定thold时间。

67

  • tcd≥thold-tccq
  • 上式被称为保持时间约束或最小延迟约束;
  • 限制了通过组合逻辑的最小延迟。

68

  • 在实际应用中,经常将触发器设计成thold=0,以保证保持时间约束在各种情况下都可以满足;
  • 保持时间约束非常重要,如果一旦违反则必须重新设计电路;
    • 与建立时间约束不同,不能通过调整时钟周期来改正。
  • 因此一旦违反保持时间约束会产生非常严重的后果。

时序分析

69

70

71

时序逻辑模块

基于SystemVerilog HDL的时序逻辑设计

  • SystemVerilog使用一些特殊的编码风格(idioms)描述锁存器、触发器和状态机;
  • 其他的编码风格虽然可以正确的进行仿真,但是综合后会产生错误的电路。

always过程快的时序逻辑建模

  • always过程块分为三种类型:
    • always_comb(描述组合逻辑),always_latch,always_ff(后两者用于描述时序逻辑)。
  • always过程块结构如下:
1
2
always @(sensitivity list)
statements;
  • sensitivity list是敏感事件列表,当列表中的事件产生时,过程快中的语句开始工作。

寄存器建模

1
2
3
4
5
6
module flop(input logic clk,
input logic [3:0]d,
output logic [3:0]q);
always_ff @(posedge clk)
q<=d;
endmodule

72

  • 使用正边沿D触发器实现;
  • always_ff用来表示触发器;
  • posedge clk表示clk信号上升沿;
  • <=是非阻塞赋值,暂时可以把它看做是普通的赋值语句。

带复位端的寄存器建模

同步复位功能

1
2
3
4
5
6
7
8
module flopr(input logic clk,
input logic reset,
input logic [3:0]d,
output logic [3:0]q);
always_ff @(posedge clk)
if(reset) q<=4'b0000;
else q<=d;
endmodule

73

异步复位功能

1
2
3
4
5
6
7
8
module flopr(input logic clk,
input logic reset,
input logic [3:0]d,
output logic [3:0]q);
always_ff @(posedge clk,posedge reset)
if(reset) q<=4'b0000;
else q<=d;
endmodule

74

带使能端的寄存器建模

1
2
3
4
5
6
7
8
9
module flopren(input logic clk,
input logic reset,
input logic en,
input logic [3:0]d,
output logic [3:0]q);
always_ff @(posedge clk,posedge reset)
if(reset) q<=4'b0000;
else if(en) q<=d;
endmodule

75

锁存器

1
2
3
4
5
6
module latch(input logic clk,
input logic [3:0]d,
output logic [3:0]q);
always_latch
if(clk) q<=d;
endmodule

76

  • 不是所有的综合工具都能很好地支持锁存器;
  • 除非你明确地知道工具支持锁存器,或者你有理由使用锁存器;
  • 最好不要使用锁存器而是使用边沿触发器;
  • 此外还要防止HDL代码意外生成锁存器。

阻塞赋值 VS 非阻塞赋值

<=是非阻塞赋值

  • 与其他的语句同时工作

=是阻塞赋值

  • 按照语句在代码中的顺序依次工作

77

赋值语句使用规则

  • 同步时序逻辑电路中使用always_ff @(posedge clk)和非阻塞赋值<=
1
2
always_ff @(posedge clk)
q<=d;
  • 简单的组合逻辑电路中使用持续赋值语句assign
1
assign y=a&b;
  • 使用always_comb和阻塞赋值语句=描述复杂组合逻辑
1
2
3
4
5
6
always_comb begin
p=a^b;
g=a&b;
s=p^cin;
cout=g|(p&cin);
end
  • 不要再多余1个always语句块或者连续赋值语句中对同一个信号赋值。

计数器

定义

  • N位二进制计数器
    • 输入:时钟、复位信号;
    • 输出:N位计数结果。
  • 功能:时钟上升沿到达时将结果加1并输出;
  • 能够实现循环计数
    • 例如:000,001,010,011,100,101,110,111,000,001…
  • 典型应用
    • 数字时钟、程序计数器(PC)。

78

建模

1
2
3
4
5
6
7
8
module counter #(parameter N=8)
(input logic clk,
input logic reset,
output logic [N-1:0]q);
always_ff @(posedge clk,posedge reset)
if(reset) q<=0;
else q<=q+1;
endmodule

79

移位寄存器

  • 移位寄存器
    • 输入:时钟、串行输入Sin
    • 输出:串行输出Sout、N位并行输出QN-1:0
  • 功能:在时钟的每一个上升沿,从Sin移入一个新的位,寄存器中所有内容都向前移动一位,最前面的位移入Sout
  • 可以看做是一个串行到并行的转换器,每个周期从Sin输入一位,N个周期后可以通过QN-1:0直接访问N位输入;
  • 实现:N个D触发器串联。

80

带并行加载的移位寄存器

定义

  • 带并行加载的移位寄存器
    • 输入:在移位寄存器基础上增加了加载(Load)信号和并行输入信号D1:0
  • 功能:
    • Load=1,并行加载位;
    • Load=0,移位寄存器。
  • 可以实现
    • 串行转并行(Sin到QN-1:0);
    • 并行转串行(DN-1:0到Sout)。

81

建模

1
2
3
4
5
6
7
8
9
10
11
12
13
module shiftreg #(parameter N=8)
(input logic clk,
input logic reset,load,
input logic sin,
input logic [N-1:0]q,
output logic [N-1:0]q,
output logic sout);
always_ff @(posedge clk,posedge reset)
if(reset) q<=0;
else if(load) q<=d;
else q<={q[N-2:0],sin};
assign sout=q[N-1];
endmodule

82

有限状态机建模

定义

  • 有限状态机主要包含三个模块:
    • 状态寄存器
      • 存储当前时刻的状态;
      • 状态在下一个有效时钟沿发生改变。
    • 组合逻辑
      • 计算下一个状态(次态逻辑);
      • 计算电路的输出(输出逻辑)。
  • 在状态机建模时也应包含三个对应的语句块。

83

实例:3分频计数器

3分频计数器

  • 一个时钟输入;
  • 一个输出;
  • 每三个时钟周期后输出产生一个周期的高电平;
  • 输出是时钟的三分频。

84

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module divideby3FSM(input logic clk,
input logic reset,
output logic q);
typedef enum logic [1:0]{S0,S1,S2} statetype;
statetype [1:0] state, nextstate;
//寄存器
always_ff @(posedge clk,posedge reset)
if(reset) state<=S0;
else state<=nextstate;
//次态逻辑
always_comb
case(state)
S0:nextstate=S1;
S1:nextstate=S2;
S2:nextstate=S0;
default:nextstate=S0;
endcase
//输出逻辑
assign q=(state==S0);
endmodule

存储器阵列

  • 一种有效的存储大量数据的模块;
  • 每个N位地址都可以读出或写出M位的数据
    • 数据:存储的内容;
    • 地址:数据的索引。

85

  • 存储器由一个二维存储单元阵列构成;
  • 每个位单元存储1位数据;
  • 一个N位地址M位数据的阵列:
    • 有2N行和M列;
    • 深度(Depth):阵列的行数;
    • 宽度(Width):阵列的列数;
    • 阵列的总大小(Array Size):宽度×深度=2N×M;
    • 字(Word):每行数据都称为一个字。

86

87

88

位单元

  • 存储器阵列由位单元(bit cell)阵列组成;
  • 每个位单元存储1位数据;
  • 每一个位单元与一个字线(wordline)和一个位线(bitline)相连。

89

90

存储器的结构

字线

  • 与使能端相似;
  • 用于控制阵列中一行数据的读/写;
  • 对应着唯一的地址;
  • 同一时刻至多有一个字线为高电平。

91

存储器的类型

  • 两种主要的类型
    • 随机访问存储器(Random Access Memory):易失的(volatile)
      • 动态随机访问存储器(DRAM):计算机的主存;
      • 静态随机访问存储器(SRAM):CPU中的高速缓存。
    • 只读存储器(Read Only Memory):非易失的(non-volatile)
  • RAM和ROM的命名是由于历史的原因
    • ROM也可以是随机访问的,大多数现代ROM也是可读写的。

DRAM VS SRAM

92

93

几种存储器的比较

存储器类型 每个位单元的晶体管数 成本 延迟
触发器 ≈20
SRAM 6 中等 中等
DRAM 1
ROM:读速度快,写速度较慢

存储器端口

94

寄存器文件

95

  • 寄存器文件(Register files)通常是一个小型多端口SRAM阵列;
  • 上图是一个32寄存器×32位的3端口寄存器文件;
  • 由两个读端口A1/RD1和A2/RD2;
  • 一个写端口A3/WD3;
  • 地址线均为5位,可寻址25=32个寄存器;
  • 可以同时读两个寄存器和写一个寄存器。

RAM建模

1
2
3
4
5
6
7
8
9
10
module ram #(parameter N=6,M=32)
(input logic clk,we,
input logic [N-1:0]adr,
input logic [M-1:0]din,
output logic [M-1:0]dout);
logic [M-1:0] mem[2**N-1:0];//**位幂运算,即2的N次方-1
always_ff @(posedge clk)
if(we) mem[adr]<=din;
assign dout=mem[adr];
endmodule

96

ROM建模

1
2
3
4
5
6
7
8
9
10
module rom(input logic [1:0]adr,
output logic [2:0]dout);
always_comb
case(adr)
2'b00:dout<=3'b011;
2'b01:dout<=3'b110;
2'b10:dout<=3'b100;
2'b11:dout<=3'b010;
endcase
endmodule