题解 | #格雷码计数器#
格雷码计数器
https://www.nowcoder.com/practice/311754bcd45d42eb8d981eeddbdf1e43
思路
格雷码
1.是什么?
格雷码是一种二进制数系统,其中相邻的两个数之间只有一个比特位不同。
2.使用格雷码的好处?
- 减少错误传播: 相邻的格雷码值只有一位二进制位不同,这意味着在格雷码计数器中,只有一个位的变化会导致一个格雷码值的变化。这减少了在数字系统中错误传播的可能性,因为只有一个位的变化会引起格雷码的改变。
- 解决"反射"问题: 在普通的二进制计数器中,当计数器从一个值转移到下一个值时,可能会出现多个位的变化,这可能会导致瞬态信号,称为"反射"。使用格雷码可以消除这种反射问题,因为只有一个位的变化。
- 简化同步电路设计: 由于格雷码中只有一个位的变化,因此可以更容易地设计同步电路。在时钟上升沿或下降沿,只需要考虑一个位的变化,而不必担心多个位同时变化带来的问题。
- 减少功耗: 由于反射问题的消除,格雷码可以减少数字系统中的功耗,因为减少了瞬态信号和不必要的位变化。
3.格雷码和二进制数的?
- 格雷码--->二进制数:
assign gray_code = {binary_code[3], binary_code[3] ^ binary_code[2], binary_code[2] ^ binary_code[1], binary_code[1] ^ binary_code[0]};
- 二进制--->格雷码
assign gray_code = binary_code ^ (binary_code >> 1);
4.注意题目是每隔两个周期计数一次。
代码
`timescale 1ns/1ns module gray_counter( input clk, input rst_n, output reg [3:0] gray_out ); reg [3:0]binary_code; reg cnt; always @(posedge clk or negedge rst_n) begin if (!rst_n)begin binary_code<=0; cnt<=0; gray_out<=0; end else begin if (!cnt)binary_code<=binary_code+1; cnt<=cnt+1; gray_out<=binary_code^(binary_code>>1); end end // always @(posedge clk or negedge rst_n) begin // if (!rst_n)gray_out<=0; // else gray_out<=binary_code^(binary_code>>1); // end endmodule
注意点
- 我本以为,如果用第24~27行代替第20行,那么gray_out的变化会比binary_code延迟一拍。如果使用第20行代替第24~27行的话,那么gray_out的变化会和binary_code的变化同步。然后实验了才发现,两种写法,gray_out的变化都会比binary_code延迟一拍。