由于在网上和书上看到的流水线结构全是基于阻塞赋值的,结果输出是正确的(大部分时间),但是存在亚稳态的情况,
我个人的观点是觉得在always块中建立时序电路的话,最好用非阻塞赋值。读者可以自己进行验证,阻塞赋值偶尔会使结果出现错误的。
所以,在别人基础上更改了一下代码,改为非阻塞赋值,例程如下:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// 16位2级流水线加法器
// 水若寒飞扬
//////////////////////////////////////////////////////////////////////////////////
module adder16_2(cout,sum,clk,cina,cinb,cin,rst);
input [15:0] cina,cinb;
input clk,cin;
input rst;
output [15:0] sum;
output cout;
reg cout,cout1;
reg[7:0] sum1; //sum1是低8位相加结果
reg [15:0] sum;//sum是16位结果
reg count2;
reg [7:0] sum2; //存储中间结果
//第一级流水
always @(posedge clk) begin //低8位先加
if(rst)
{cout1,sum1}<=0;
else
{cout1,sum1}<=cina[7:0]+cinb[7:0]+cin;
//{cout1,sum1}<={cina[7],cina[7:0]}+{cinb[7],cinb[7:0]}+cin;//有符号数
end
//第二级流水
always @(posedge clk) begin//高8位再加
if(rst) {cout,sum}<=0;
else begin
{count2,sum2}<=cina[15:8]+cinb[15:8];
{cout,sum}<={{count2,sum2}+cout1,sum1};
end
//{cout,sum}<={{cina[15],cina[15:8]}+{cinb[15],cinb[15:8]}+cout1,sum1};//有符号数
end
endmodule
RTL结构图:
仿真图: