我一直听说没有由code到circuit就只是入门了。实在没办法了。我想了一招,一个一个的写,然后看RTL,然后分析。这是第一篇。
1、触发器。
没有复位,置位。posedge clk 是触发沿时钟。一直输出8‘h55.
module test_io(
input clk,
input rst_n,
output [7:0] test,
input in
);
reg [7:0] test_r;
reg [7:0] t1;
always @(posedge clk) begin
test_r <= in;
end
assign test = test_r;
endmodule
如果位数不匹配:只匹配低位,高位为0.
同步复位,其实就是在d触发器输入端加一个选择器,是输入0还是in。现在可知选择器可以使用if描述。if还要详细的编写。
异步复位,在always中加入negedge rst_n,即是d触发器的清零使能端。
这是异步置位端,描述只要将0改为1即可。但是RTL却是如上图。可以推知这和器件有关。于是我将它们的编译报告做了比较:
可知在使用异步置位时多使用了一个total conmbinational functions。这就表明和具体的器件有关。要了解器件的结构。
always @(posedge clk) begin
if(!rst_n) begin
test_r <= 1;
end
else begin
test_r <= in;
end
end
同步置位。可知和同步复位没有结构上的差异。但是有一个问题我错了:就是在位数不匹配的时,是先匹配高位。即有8’h80.
always @(negedge clk) begin
if(!rst_n) begin
test_r <= 1;
end
else begin
test_r <= in;
end
end
对于下降沿触发的就是在前有o符号。比如在上图中。还有如果是低电平选择前也有o比如rst_n.
in成为d触发器的使能端。
此时d触发器也存在,我总结触发器存在的原因有二:1、需要同步输出。2、需要保持数据。只要有一个满足就会存在触发器。
总结:对于边沿触发的reg型,我认为到此结束了。
--------------------------------------------------------------------------------------------------------------------------------------------------------
现在描述电平敏感即always 中没有posedge or negedge.
可知此时的test_r被综合掉了。而只有一个选择器。而且电平clk接地了。还有我将clk改成rst_n也是一样的RTL.对于电平敏感的always块中,reg有可能根据实际的作用被综合掉。
always @(rst_n) begin
if(!rst_n) begin
test_r <= in;
end
end
assign test = test_r;
此时的RTL是锁存器。可知电平敏感的always将有可能产生锁存器。注意此时只有if没有else。这就可以知道了,在电平敏感的always中如果数据需要保持,就会产生锁存器,如果不需要保持就不会产生锁存器。这也是锁存器的功能,锁存数据。在也可以知道产生触发器,也是因为在always块中保持数据。如果不需要保持数据,也不会产生触发器。
always @(rst_n or clk) begin
if(!rst_n) begin
test_r <= in;
end
else if(clk) begin
test_r <= in_2;
end
else
test_r <= 1;
end
此时的数不需要保持,所以只有数据选择器。
由于需要保持数据,即有锁存器,根据描述产生清零端,使能端。
数据需要保持且产生置位端,使能端。
还有一点:我认为做这些不是要做到由RTL到代码。而是要做到,由代码到RTL。