这是地球人都知道的编码风格,但是在阅读别人的代码的时候,还是经常看到组合逻辑和时序逻辑混在一起。怎样才能很好地将组合逻辑电路和时序逻辑电路分开编码呢?我觉得应该对常见的组合电路和时序电路的编码非常熟悉,在设计中才能将代码和电路结合起来,才能很好地区分哪些是组合逻辑,哪些是时序逻辑。下面举一个例子说明:
源代码1:
module code_style(clk,rst_n,data_out);
input clk ;
input rst_n ;
output data_out;
reg [2:0] cnt ;
reg [7:0] data_out;
always @ (posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
cnt <= 3'b0;
data_out <= 8'b0;
end
else
begin
cnt <= cnt + 1'b1;
case(cnt)
3'b000 : data_out <= 8'b0000_0001;
3'b001 : data_out <= 8'b0000_0010;
3'b010 : data_out <= 8'b0000_0100;
3'b011 : data_out <= 8'b0000_1000;
3'b100 : data_out <= 8'b0001_0000;
3'b101 : data_out <= 8'b0010_0000;
3'b110 : data_out <= 8'b0100_0010;
3'b111 : data_out <= 8'b1000_0000;
default : data_out <= 8'b0000_0000;
endcase
end
end
endmodule
读上面的程序,我们知道,是把计数值进行译码,很多人都知道,计数器是时序逻辑,译码是组合逻辑,于是可以将程序改写成:
源代码2:
module code_style(clk,rst_n,data_out);
input clk ;
input rst_n ;
output data_out ;
reg [2:0] cnt ;
reg [7:0] data_out;
always @ (posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0) cnt <= 3'b0;
else cnt <= cnt + 1'b1;
end
always @ (cnt)
begin
case(cnt)
3'b000 : data_out = 8'b0000_0001;
3'b001 : data_out = 8'b0000_0010;
3'b010 : data_out = 8'b0000_0100;
3'b011 : data_out = 8'b0000_1000;
3'b100 : data_out = 8'b0001_0000;
3'b101 : data_out = 8'b0010_0000;
3'b110 : data_out = 8'b0100_0010;
3'b111 : data_out = 8'b1000_0000;
default : data_out = 8'b0000_0000;
endcase
end
endmodule
源代码2这样书写将组合逻辑和时序逻辑分开写了,但是需要说明的是,这样改写是错误的,我们仿真就可以看出其中的玄机,
源代码一仿真结果:
源代码二仿真结果:
为什么会这样呢?实际上源代码一中包含了两个时序逻辑,在译码完后,需要将译码结果寄存,然后再输出,而源代码二中并未寄存,但是源代码一中又不能很好地观察出来,所以真正的将组合逻辑和时序逻辑分开,而且时序也正确应该是下面的格式:
module code_style(clk,rst_n,data_out);
input clk ;
input rst_n ;
output data_out;
reg [2:0] cnt ;
reg [7:0] data_out_reg ;
reg [7:0] data_out ;
always @ (posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0) cnt <= 3'b0;
else cnt <= cnt + 1'b1;
end
always @ (cnt)
begin
case(cnt)
3'b000 : data_out_reg = 8'b0000_0001;
3'b001 : data_out_reg = 8'b0000_0010;
3'b010 : data_out_reg = 8'b0000_0100;
3'b011 : data_out_reg = 8'b0000_1000;
3'b100 : data_out_reg = 8'b0001_0000;
3'b101 : data_out_reg = 8'b0010_0000;
3'b110 : data_out_reg = 8'b0100_0010;
3'b111 : data_out_reg = 8'b1000_0000;
default : data_out_reg = 8'b0000_0000;
endcase
end
always @ (posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0) data_out <= 8'b0;
else data_out <= data_out_reg;
end
endmodule
这样组合逻辑和时序逻辑的层次就非常清楚了
用户1562225 2012-4-14 17:33