写 HDL 语言,归根到底还是通过综合器形成底层电路,工程师只需要写功能性代码即可,不用考虑电路时怎么样的,大大加快了项目的开发进度,把代码综合成电路,不得 不佩服做编译器的这些公司是多么的牛逼!!They are makers , we are just players !
然而,只写代码,是不是总觉得不放心?是不是总觉得心里边隔着层什么?形成的电路到底是什么样的?其实,代码只是手段,我们的目标是电路,必须懂底层的电路,才能说是一名合格的硬件逻辑工程师,而且,能把代码和电路映射起来,也有助于形成良好的代码风格 ! 当你看到代码,脑子中出现的是电路时, U succeed !
Quartus II 的工具 Technology Map Viewer 就是FPGA的底层资源形成的电路,通过下面的例子,看看状态机具体是怎么实现的
parameter state0=4'd0,state1=4'd1,state2=4'd2,state3=4'd3,state4=4'd4;
reg [3:0] state;
reg reset;
always@(posedge clk or negedge rst_n)
if(!rst_n)
reset<=1'b0;
else reset<=rst_n;
always@(posedge clk )
if(!reset)
begin
dataout1<=4'd3;
//state<=state0;
end
else case(state)
state0: if(!datain1)
begin
state<=state1;
dataout1<=4'd1;
end
else if(!datain2)
begin
state<=state2;
dataout1<=4'd2;
end
else if(!datain3)
begin
state<=state3;
dataout1<=4'd3;
end
else if(!datain4)
begin
state<=state4;
dataout1<=4'd4;
end
state1: if(!datain1)
begin
state<=state0;
dataout1<=4'd5;
end
else if(!datain2)
begin
state<=state2;
dataout1<=4'd2;
end
else if(!datain3)
begin
state<=state3;
dataout1<=4'd3;
end
else if(!datain4)
begin
state<=state4;
dataout1<=4'd4;
end
state2: if(!datain1)
begin
state<=state1;
dataout1<=4'd1;
end
else if(!datain2)
begin
state<=state0;
dataout1<=4'd5;
end
else if(!datain3)
begin
state<=state3;
dataout1<=4'd3;
end
else if(!datain4)
begin
state<=state4;
dataout1<=4'd4;
end
state3: if(!datain1)
begin
state<=state1;
dataout1<=4'd1;
end
else if(!datain2)
begin
state<=state2;
dataout1<=4'd2;
end
else if(!datain3)
begin
state<=state0;
dataout1<=4'd5;
end
else if(!datain4)
begin
state<=state4;
dataout1<=4'd4;
end
state4: if(!datain1)
begin
state<=state1;
dataout1<=4'd1;
end
else if(!datain2)
begin
state<=state2;
dataout1<=4'd2;
end
else if(!datain3)
begin
state<=state3;
dataout1<=4'd3;
end
else if(!datain4)
begin
state<=state0;
dataout1<=4'd5;
end
default: state<=state0;
endcase
always@(posedge clk1 )
if(!reset1)
begin dataout2<=4'd0; end
else if(state==state0)
dataout2<=4'd5;
一个很简单的状态机,具体到电路 并没有对应的 状态寄存器[3:0]state,各个状态也不是像parameter定义的那样,每个状态4位表示。而是每个状态用一个 D触发器来表示, 分别是 state.state0,state.state1,state.state2,state.state3,state.state4,在state0 时,对应的state.state0触发器输出高电平,具体的电路结构,是看不出状态机的,“一堆电路而已”,只是实现的功能,就是上述状态机的代码 !
以状态state0 为例,转移到state0 ,跟当前状态有关,也跟4个输入有关,对应到电路中:D 触发器state.state0 是输出,datain1,datain2,datain3,datain4和state.state1,state.state2,state.state3,state.state4 作为输入
从state1跳转到state0过程:
第 一个时钟上升沿后,来到状态state1( D触发器 state.state1变为高电平),这个输出高电平 进入组合逻辑,即一系列的LUT ,外部的输入信号datain1 等也输入这些组合逻辑,最后组合逻辑的输出 接到 触发器 state.state1的输入端 D端口 ,等到第二个时钟上升沿时,state.state1输出 D端数据到 Q端口 ,如果 外部输入条件满足,那么上升沿来时state.state1 输入端口D应该是高电平,第二个时钟沿后,Q输出高电平,这样,状态state1 跳转到state0 ;由于条件不满足从state1跳到state2,所以state1到state2的组合逻辑输出低电平,上升沿后state.state2,输出也是低。
这里有个问题,state.state1 和state.state0 两个触发器属于,“源同步”的关系,所以state.state1到state.state0之间经过的组合逻辑不能太多,必须满足state.state0的 “建立/保持”时间 !
比如: 时钟频率特别高,而state.state1到state.state0 之间的组合逻辑特别多,那么不满足“建立/保持”时间,状态就跳转不成功,也就是根本没有检测到state1的出现,又怎么能跳转到state0 呢??
中 间的组合逻辑是什么呢? 是 判断状态转移的条件。如果说状态转移的条件就是在 state1时,datain1 输入高电平,下一个状态跳转到 state1,那么组合逻辑 就是一个LUT,输入是 datain1和state.state1 ,此LUT的输出接到state.state0的输入端。 JUST SO EASY !
还有个问题,对应状态的输出怎么实现的?其实和状态转移是同样的道理,看上边程序,dataout1的输出与当前状态和输入datain 有关。也就是各个datain和状态触发器作为输入,dataout作为输出。状态寄存器state.state0,state.state1,state.state2,state.state3,state.state4 的输出和各个输入datain1,datain2,datain3,datain4 一同输入到 组合逻辑 LUT 中,组合逻辑的输出接到 寄存器 dataout1 。
下篇博文,把状态机改成三段式的,再探究底层电路结构 。。。。
Alwin 2014-3-20 23:15
用户1731878 2014-3-18 12:46