LED流水灯
实现一个LED流水灯,切换周期为1s。代码如下:
module led(
input clk_50m,
input rst_n,
output[3:0] led
);
localparam TOTAL_TICK = 27'd50000000; // 1s
reg[3:0] led_r;
reg[26:0] cnt;
assign led = led_r;
// 写法一
//always @(posedge clk_50m or negedge rst_n) begin
// if(!rst_n)
// cnt <= 27'd0;
// else if(cnt == TOTAL_TICK - 1)
// cnt <= 27'd0;
// else
// cnt <= cnt + 27'd1;
//end
// 写法二
always @(posedge clk_50m or negedge rst_n) begin
if(!rst_n)
cnt <= 27'd0;
else if(cnt < TOTAL_TICK - 1)
cnt <= cnt + 27'd1;
else
cnt <= 27'd0;
end
always@(posedge clk_50m or negedge rst_n) begin
if(!rst_n)
led_r <= 4'b0001;
else if(cnt == TOTAL_TICK - 1)
led_r <= {led_r[2:0], led_r[3]}; // 这是一个循环移位
else
led_r <= led_r;
end
endmodule
写法二的RTL视图如下。其中:
①表示的语句如下。
else if(cnt < TOTAL_TICK - 1)
②表示的语句如下:
cnt <= cnt + 27'd1;
③表示的语句如下,是一个选择器。当①表示的语句不满足时,选择27‘h0输出给cnt[26:0],即else分支;否则,选择②计算的结果输出给cnt[26:0]。
else if(cnt < TOTAL_TICK - 1)
cnt <= cnt + 27'd1;
else
cnt <= 27'd0;
④表示将27位的cnt[26:0]扩展为高位为0的32位信号A[31:0],“=”表示的语句如下。当该语句满足时,寄存器led[0]和led[3…1]使能,执行移位。
else if(cnt == TOTAL_TICK - 1)
写法一的RTL视图如下。相比写法二,写法一的RTL少了一个“<”的operator,理论上可以减少面积。
计数器
第一种写法如下。输出端口不加reg。
module counter(
input clk_50m,
input rst_n,
output[3:0] cnt
);
reg[3:0] cnt_r;
assign cnt = cnt_r;
always @(posedge clk_50m or negedge rst_n) begin
if(!rst_n)
cnt_r <= 4'd0;
else
cnt_r <= cnt_r + 4'd1;
end
endmodule
第一种写法的RTL视图如下。
第二种写法如下。输出端口加reg。
module counter(
input clk_50m,
input rst_n,
output reg[3:0] cnt
);
always @(posedge clk_50m or negedge rst_n) begin
if(!rst_n)
cnt <= 4'd0;
else
cnt <= cnt + 4'd1;
end
endmodule
第二种写法的RTL视图如下。
可以看到第二种写法的RTL视图中,寄存器为“cnt[0]~reg[3…0]”,我不是很懂这个表示方式的意义。
把LED流水灯代码的输出加上reg后的RTL视图如下。似乎不是很好理解最后输出的那两级寄存器的表示方式。