关于二进制转格雷码的原理文章,这里不做赘述,主要讨论几种RTL编码的写法的讨论。
二进制转格雷码公式:
g[n-1]=b[n-1], g[i]=b[i]^b[i+1], i=[0,1,...,n-2]
b表示二进制值,g表示格雷码值。
方法1:
从公式中可以看出,格雷码的最低位g[0]等于b[0] ^ b[1],以此类推格雷码的次高位g[n-2]等于b[n-2] ^ b[n-1],而最高位等于g[n-1]=b[n-1]。可以通过for循环实现。
module BIT2GRAY_CBB #(
parameter WIDTH = 8
)(
input [WIDTH-1:0] bin ,
output reg [WIDTH-1:0] gray
);
always @ ( * ) begin : BIT2GRAY
integer i;
for (i = 0; i < WIDTH - 1; i = i + 1) begin
gray[i] = bin[i] ^ bin[i + 1];
end
gray[WIDTH-1] = bin[WIDTH-1];
end
endmodule
方法2:
因为方法1计算过程:格雷码值当前位等于二进制当前位与高一位相异或,只有最高位是赋值相等。可将二进制右移一位然后最高位补0得到的值,然后再与二进制整体做异或。因为二进制的最高值与1‘b0异或始终等于二进制的最高值。
module BIT2GRAY_CBB #(
parameter WIDTH = 8
)(
input [WIDTH-1:0] bin ,
output reg [WIDTH-1:0] gray
);
always @ ( * ) begin : BIT2GRAY
gray = bin ^ {1'b0, bin[WIDTH-1:1]};
end
endmodule
方法3:
因为是异或运算,因此也可以通过比较实现,二者相同赋值1‘0,否则赋值1'b1。
module BIT2GRAY_CBB #(
parameter WIDTH = 8
)(
input [WIDTH-1:0] bin ,
output reg [WIDTH-1:0] gray
);
always @ ( * ) begin : BIT2GRAY
integer i;
for (i = 0; i < WIDTH - 1; i = i + 1) begin
if (bin[i] == bin[i + 1])
gray[i] = 1'b0;
else
gray[i] = 1'b1;
end
gray[WIDTH-1] = bin[WIDTH-1];
end
endmodule
通过Vivado选择相同的器件,综合结果三者的电路图完全相同,结果符合预期。
通过对以上代码的分析,因为最高位直接赋值,因此应该有7个LUT2资源的消耗,该LUT2用于做异或运算,综合出的电路图如下,符合预期。
二进制转换格雷码在异步模块中最基本且常用的数据操作,可以做成CBB。
若有不正确的地方,欢迎大家指正。