Menu Close

状态机中状态编码格式

状态机中状态编码格式

在上几节内容中介绍的状态机状态都是采用自然码的编码格式,虽然简单但有时为了可靠性还会选择其它的编码方式,比较常用的由格雷码(Gray code)和独热吗(one hot code)。下面就格雷码和独热码编码方式及优缺点加以介绍。

  1. 格雷码

格雷码是一种可靠性编码,与自然二进制编码不同格雷码的编码每次只有一位不同,因此在状态转换时是错误最小的编码方式。 在数字系统中,常要求代码按一定顺序变化。例如,按自然数递增计数,若采用8421码,则数0111变到1000时四位均要变化,而在实际电路中,4位的变化不可能绝对同时发生,则计数中可能出现短暂的其它代码(1100、1111等)。在特定情况下可能导致电路状态错误或输入错误。使用格雷码可以避免这种错误。著名的数字调制编码QAM就采用了格雷码的编码方式,同样著名的数字逻辑化简得卡诺图也是采用格雷码编码方式。格雷码具有循环、单步、反射、自补等特点。表1,表2,表3,分别列出了2位,3位,4位自然二进制码与格雷码的关系。有关更多的理论请参照后续推出得编码理论部分教程。

表1

序号 自然2进制码 格雷码 独热码
0 00 00 0001
1 01 01 0010
2 10 11 0100
3 11 10 1000

表2

序号 自然2进制码 格雷码 独热码
0 000 000 0000_0001
1 001 001 0000_0010
2 010 011 0000_0100
3 011 010 0000_1000
4 100 110 0001_0000
5 101 111 0010_0000
6 110 101 0100_0000
7 111 100 1000_0000

 

表3

序号 自然2进制码 格雷码 独热码
0 0000 0000 0000_0000_0000_0001
1 0001 0001 0000_0000_0000_0010
2 0010 0011 0000_0000_0000_0100
3 0011 0010 0000_0000_0000_1000
4 0100 0110 0000_0000_0001_0000
5 0101 0111 0000_0000_0010_0000
6 0110 0101 0000_0000_0100_0000
7 0111 0100 0000_0000_1000_0000
8 1000 1100 0000_0001_0000_0000
9 1001 1101 0000_0010_0000_0000
10 1010 1111 0000_0100_0000_0000
11 1011 1110 0000_1000_0000_0000
12 1100 1010 0001_0000_0000_0000
13 1101 1011 0010_0000_0000_0000
14 1110 1001 0100_0000_0000_0000
15 1111 1000 1000_0000_0000_0000

例1:4位自然2进制数到格雷码的转换

自然二进制码到格雷码得转换,保留自然二进制码得最高位,其它位采用本位与该位相邻的高位异或得到。数学公式描述如下:

公式表示: Gn=Bn

Gi= Bi+1  ^Bi  (0=<i<=n-1)

(G:格雷码,B:二进制码)

Verilog 代码如下:



  module Binary_Gray


  (


  	input	[3:0]  Bin,


  	output  [3:0]  Gray


  );


  	assign  Gray[3]=Bin[3];


  	assign  Gray[2]=Bin[3]^Bin[2];


  	assign Gray[1] =Bin[2]^Bin[1];


  	assign Gray[0] =Bin[1]^Bin[0];


  endmodule


  

例2,4位二进制格雷码转换为自然2进制码

由格雷码到自然二进制转换,保留格雷码的最高位,次高位由最高位与次高位异或得到,之后的各位由上一位的计算结果(二进制码)与本位(格雷码)异或。

公式表示:Bn=Gn

Bi= Bi+1 ^ Gi

(G:格雷码,B:二进制码)

Verilog 代码如下:


  module Gray_Bin

  (


  	input  [3:0]  Gray,


  	output[3:0]  Bin

  );


  	assign Bin[3]=Gray[3];

  	assign Bin[2]=Bin[3]^Gray[2];

  	assign Bin[1]=Bin[2]^Gray[1];

  	assign Bin[0]=Bin[1]^Gray[0];

  endmodule

  

2. 独热码

独热码是每位只有一位为1,其它都为零。这种编码方式每次也只有两位发生变化,从误差最小的角度看不如格雷码,但独热码的编码和解码都比较简单。

3. 编码方式比较,如表2

 

表2

二进制编码 格雷码 独热码
优点 编码密度高;

便于理解和调试;

编码密度高;

安全可靠;

占用资源少
缺点 不利于综合器的化简;

判断状态时资源占用多;

判断状态时占用资源多 编码密度低
适用范围 状态多,逻辑复杂,资源充足的情况下 状态多,对状态机稳定性要求高的情况 状态少,判断条件复杂的情况
  1. 将按键去抖程序按格雷码的编码方式改写

module deboucing

(

input             rst,

input             clk,

input             ms_p, //毫秒脉冲

input             sw_in,//按键输入

output          sw_out//按键输出

 

);

localparam [1:0] pd_capture=0,//按下捕获

pd_deboucing=1,

rls_capture=3,//释放捕获(release)

rls_deboucing=2;

reg  [2:0]        bn_r; //按键输入锁存

reg               bn_hp_debouce; //按键_高电平脉冲_去抖

reg   [3:0]       deb_count;

reg   [1:0]    deb_st; //按键去抖状态机的状态

assign        sw_out=bn_hp_debouce;

 

always@(posedge clk or posedge rst )

if(rst) begin

bn_r=0;

deb_st=pd_capture;

deb_count=0;

bn_hp_debouce=0;

end

else begin

bn_r={bn_r[1:0],sw_in}; //按键三次锁存,消除亚稳态

case(deb_st)

pd_capture: begin

deb_count=0;

bn_hp_debouce=0;

if(bn_r[2])

deb_st=pd_deboucing;

end

pd_deboucing: begin

if(~bn_r[2])

deb_st=pd_capture;

else if(deb_count>=10)

deb_st=rls_capture;

else if(ms_p)

deb_count=deb_count+1;

end

rls_capture: begin

deb_count=0;

if(~bn_r[2])

deb_st=rls_deboucing;

end

rls_deboucing: begin

if(bn_r[2])

deb_st=rls_capture;

else if(deb_count>=10) begin

deb_st=pd_capture;

bn_hp_debouce=1’b1;

end

else if(ms_p)

deb_count=deb_count+1;

end

default: deb_st=pd_capture;

endcase

end

endmodule

[/code]

例4:将按键去抖程序状态机的状态按独热码方式实现

module deboucing

(

input             rst,

input             clk,

input             ms_p, //毫秒脉冲

input             sw_in,//按键输入

output          sw_out//按键输出

 

);

 

localparam [3:0] pd_capture=4‘b001,//按下捕获

pd_deboucing=4’b0010,

rls_capture=4’b0100,//释放捕获(release)

rls_deboucing=4’b1000;

 

reg  [2:0]        bn_r; //按键输入锁存

reg               bn_hp_debouce; //按键_高电平脉冲_去抖

reg   [3:0]       deb_count;

reg   [1:0]    deb_st; //按键去抖状态机的状态

assign        sw_out=bn_hp_debouce;

 

always@(posedge clk or posedge rst )

if(rst) begin

bn_r=0;

deb_st=pd_capture;

deb_count=0;

bn_hp_debouce=0;

end

else begin

bn_r={bn_r[1:0],sw_in}; //按键三次锁存,消除亚稳态

case(deb_st)

pd_capture: begin

deb_count=0;

bn_hp_debouce=0;

if(bn_r[2])

deb_st=pd_deboucing;

end

pd_deboucing: begin

if(~bn_r[2])

deb_st=pd_capture;

else if(deb_count>=10)

deb_st=rls_capture;

else if(ms_p)

deb_count=deb_count+1;

end

rls_capture: begin

deb_count=0;

if(~bn_r[2])

deb_st=rls_deboucing;

end

rls_deboucing: begin

if(bn_r[2])

deb_st=rls_capture;

else if(deb_count>=10) begin

deb_st=pd_capture;

bn_hp_debouce=1’b1;

end

else if(ms_p)

deb_count=deb_count+1;

end

default: deb_st=pd_capture;

endcase

end

endmodule

[/code]

以上介绍了不同的编码格式及在状态机中的使用,所使用的例子也都是比较熟悉的例子,便于把主要精力放在基本概念的理解上。

练习题:

  1. 将改写后的按键去抖程序在Quartus II下编译,观察逻辑资源及寄存器使用情况。
  2. 将改写后的按键去抖程序在Vivado下编译,观察逻辑资源及寄存器使用情况。
  3. 设计8输入的2进制自然码到格雷码的转换
  4. 设计8输入的格雷码到自然2进制码的转换。

 

Posted in FPGA, FPGA 教材教案, Verilog, 教材与教案, 文章

发表评论

您的电子邮箱地址不会被公开。

Leave the field below empty!

相关链接