如何读Vivdao中的电路图
Verilog全称是Verilog HDL,HDL即硬件描述语言(hardware description language),换言之,Verilog的所有代码,与硬件电路的器件框图是等价的,本文以跑马灯为例,结合其verilog程序,来阅读其电路图。
代码示例
跑马灯的实现非常简单,只需对时钟进行计数,到达一定的数目后,对LED灯的亮暗进行移位即可。下面只考虑两个led灯,代码如下
module flow_led(
input sys_clk,
input sys_rst,
output reg [1:0] led
);
reg [24:0] cnt ; //计数器
//计数器计时0.5s
always @(posedge sys_clk or negedge sys_rst) begin
if(!sys_rst)
cnt <= 25'd0;
else if(cnt < (25'd2500_0000 - 25'd1))
cnt <= cnt + 25'd1;
else
cnt <= 25'd0;
end
//对LED灯进行移位控制,以输出2位LED的状态
always @(posedge sys_clk or negedge sys_rst) begin
if(!sys_rst)
led <= 2'b01;
else if(cnt == (25'd2500_0000 - 25'd1))
led <= {led[0],led[1]};
else
led <= led;
end
endmodule
其功能很简单,两段触发电路,一个是让计时器递增,增长到25’d2499_9999时归零;另一个是在计时器达到25’d2499_9999时,对led进行高低位调转。
电路图
上述代码对应的电路图如下

上图左右两侧共有三个信号,分别对应verilog代码中的输入输出,即sys_clk,sys_rst以及led。
电路图中共涉及到五种逻辑器件,分别是加法器、比较器、多路选择器、寄存器、ROM。由于所有器件的名字都以RTL开头,故下面介绍各器件时略去这个前缀。
【ADD】加法器。对应代码中cnt <= cnt + 25'd1,其输入有二,一个是常量I1,另一个【I0[24:0]】与cnt_reg相连接,此cnt_reg即表示代码中的cnt。
【LT】比较器,对应代码中的cnt < (25'd2500_0000 - 25'd1)。图中并未出现减法,说明常数减法在编译期就已经被替换为常数了,即下面的17D783F。
【MUX】多路选择器,其输入端有二,一个是从加法器输出的I0,另一个是常量I1,而决定其输出哪个的,则是来自于比较器的比较结果。该器件即可对应计数器计时代码中的两个赋值语句。
【ROM】是一个25位的只读寄存器,其输入为cnt,输出一个使能信号。
【REG_ASYNC】异步复位寄存器,引脚【C】表示时钟;【CE】为使能;【D】为数据输入;【Q】为输出;【CLR】即Clear,表示清除。
- 【cnt_reg】一个25位的异步复位寄存器,用于存储计数值。sys_rst与【CLR】引脚相连,表示复位信号有效时,寄存器被清零。其输入端从多路选择器中引出,输出端递交给加法器核比较器。
- 【led_reg】两位的异步复位寄存器,用于存储led的亮暗状态。这里需要注意的是,尽管图中将输出【Q】与输入【D】连接到了一起,但并没有体现出LED灯交替变化的状况。
led <= {led[0],led[1]}的功能是将led的低位与高位呼唤,如果将其变为led <= {led[1], led[0]},实际上就和led <= led没有区别了,此时代码的功能就是保持led的初始状态。
但是,如果将led设为三位,那么代码led <= {led[1], led[0], led[2]}和led <= {led[0], led[2], led[1]}在电路图中是看不出区别的。
修改
verilog代码中,需要比较cnt和2499_9999的大小进行判断,但两次比较时,一次用了等号,一次用了小于号,下面将其改为都用等号,则电路变为

代码如下
module flow_led(
input sys_clk,
input sys_rst,
output reg [1:0] led
);
reg [24:0] cnt ; //计数器
//计数器计时0.5s
always @(posedge sys_clk or negedge sys_rst) begin
if(!sys_rst)
cnt <= 25'd0;
else
cnt <= cnt == 25'd2499_9999 ? cnt + 25'd1 : 25'd0;
end
//对LED灯进行移位控制,以输出2位LED的状态
always @(posedge sys_clk or negedge sys_rst) begin
if(!sys_rst)
led <= 2'b01;
else
led <= cnt == 25'd2499_9999 ? {led[0], led[1]} : led;
end
endmodule
更多推荐
所有评论(0)