题目
- 写一个如下循环输出的环形计数器
代码
主要有一个循环移位计数器和一个状态翻转的flag,需要注意的是循环移位计数器是从8‘h02到8’h80这样移位的,因为总共循环周期是14而不是16。在我们的代码中通过提前使得tmp == 8’h01,接着移位赋值为8‘h02,故而完成功能。
DUT
module jerky_cnt(
input wire clk,
input wire rst_n,
output wire [7:0] count
);
reg flag;
always_ff @(posedge clk or negedge rst_n) begin : proc_flag
if(~rst_n) begin
flag <= 1'b0;
end else begin
flag <= ~flag;
end
end
reg [7:0] tmp;
always_ff @(posedge clk or negedge rst_n) begin : proc_tmp
if(~rst_n) begin
tmp <= 'd1;
end else if (tmp == 8'h80) begin
tmp <= 8'h01;
end else if(flag == 1'b1)begin
tmp <= {tmp[6:0],tmp[7]};
end else begin
tmp <= tmp;
end
end
assign count = flag ? 7'd1 : tmp;
endmodule
TB
module tb_jerky_cnt();
reg clk, rst_n;
wire [7:0] out;
initial begin
clk = 'b0;
rst_n = 'b0;
# 10
rst_n = 'b1;
end
always #5 clk = ~clk;
jerky_cnt dut(
clk,
rst_n,
out
);
endmodule
仿真
小结
移位操作往往可以提高运行速度,一个标志flag可以节省资源,但是这种方式容易出错。因为如果状态情况变多,就区分不出来。这种时候可以用计算数器0-13,然后根据计数器的LSB来判断奇偶,如果为偶数就选8’h01,奇数就选1左移(count>>1)。最后还有一种方式用case语句,把所有的情况都列出来进行情况判断。