在现在的设计中,为了减少亚稳态的发生,通常需要使用可靠编码,比较常用的是Gray码,比如:跨时钟域的数据同步中,对于双端FIFO就可使用Gray码计数器来进行寻址等。
Gray码与Binary码的相互转换原理如下:
Gray->Binary:
1、Gray[n-1] = Bin[n-1]
2、Gray = Bin[i+1] ^ Bin, i=n-2,..0
即:Gray码与Binary码最高位相同,Gray码其余位等于Binary码的相应位与其相邻高位异或。
Binary->Gray:
1、Bin[n-1] = Gray[n-1]
2、Bin = Gray[n-1] ^ Gray[n-2] ^...Gray, i=n-2,..0
即:Binary码与Gray码最高位相同,Binary码其余位等于Gray码相应位与所有高位异或。
下面以Binary->Gray为例进行说明。
基本框图如下:
相关代码如下:
module gray_cnt(clk,rst_n,gray);
parameter WIDTH = 2;
input clk;
input rst_n;
output [WIDTH-1:0] gray;
reg [WIDTH-1:0] gray;
reg [WIDTH-1:0] binary;
reg [WIDTH-1:0] next_binary;
wire [WIDTH-1:0] next_gray;
always @(negedge clk or negedge rst_n) &n
assign next_gray = next_binary ^ (next_binary>>1);
always @(posedge clk or negedge rst_n) //利用clk上升沿数据同步输出
if(!rst_n)
begin
gray <= {WIDTH{1'b0}};
binary <= {WIDTH{1'b0}};
end
else //同步输出
begin
gray <= next_gray;
binary <= next_binary;
end
endmodule
测试代码如下:
`timescale 1ns/1ns
`include "./gray_cnt.v"
module gray_cnt_tb;
parameter PTR_WIDTH = 3;
parameter CYCLE = 10;
reg clk;
reg rst_n;
wire [PTR_WIDTH-1:0] gray;
initial
begin
clk = 0;
forever
#(CYCLE/2) clk = ~clk;
end
initial
begin
rst_n = 0;
#(CYCLE) rst_n =1;
end
gray_cnt u_gray_cnt(.clk(clk),
.rst_n(rst_n),
.gray(gray));
defparam u_gray_cnt.WIDTH = PTR_WIDTH;
endmodule
注:
模块调用/例化时参数的修改:
1、使用带有参数值的模块例化语句
2、使用参量重定义语句(defparam)
例如:
1、gray_cnt #(PTR_WIDTH) u_gray_cnt(...);
当有多个参数时要注意顺序,有不需要改变的参数也要全部列出
2、gray_cnt u_gray_cnt(...);
defparam u_gray_cnt.WIDTH = PTR_WIDTH;
defparam语句的位置前后都可以,不重要
因此,用第二种方法更加灵活,推荐使用。
文章评论(0条评论)
登录后参与讨论