我没有写组合逻辑部分,因为纯组合逻辑在FPGA几乎不会用到,把大量的时间浪费在那里得不偿失。脱离时序谈FPGA,就像脱离深度负反馈谈运放,有意义,但不大。
写状态机是一个经典的套路题,只要记住套路,写状态机非常简单。
3个输入:
1、控制信号A
2、时钟信号clk
3、复位信号rst_n
1个输出:
输出信号Y
控制信号A用来控制状态机在下一个时钟沿如何变幻,而输出信号Y是根据当前的状态来进行输出。所以状态机是一个时序和组合逻辑混合的模型,其中时序逻辑来控制状态的变化,组合逻辑根据当下的状态进行输出。所以编辑状态机,用两个always就可以了,一个管时序,一个管组合。
`timescale 1ns/1ns
module seq_circuit(
input A ,
input clk ,
input rst_n,
output wire Y
);
reg [1:0] q;
reg Y_reg; //Y的reg型表示
always@(posedge clk or negedge rst_n) //第一个always管时序逻辑,控制状态的改变
if(rst_n == 1'b0)
begin
q <= 2'b00;
end
else if(A == 1'b0) //当A为0时,用case描述状态的改变
case(q)
2'b00:begin
q <= 2'b01;
end
2'b01:begin
q <= 2'b10;
end
2'b10:begin
q <= 2'b11;
end
2'b11:begin
q <= 2'b00;
end
default:begin //case最后加上default是良好的习惯
q <= 2'b00;
end
endcase
else if(A == 1'b1) //当A为1时,用case描述状态的改变
case(q)
2'b00:begin
q <= 2'b11;
end
2'b01:begin
q <= 2'b00;
end
2'b10:begin
q <= 2'b01;
end
2'b11:begin
q <= 2'b10;
end
default:begin
q <= 2'b00;
end
endcase
else //if最后加上else是良好的习惯
begin
q <= 2'b00;
end
always@(*) //第二个always用来完成组合逻辑输出,输出只与状态有关,所以状态改变,Y就会改变
if(rst_n == 1'b0)
Y_reg = 1'b0;
else if(q == 2'b11)
Y_reg = 1'b1;
else
Y_reg = 1'b0;
assign Y = Y_reg;
endmodule
状态机是时序和组合的混合,所以在编译是,我们用一个always管时序,一个always管混合,从这个地方出发进行思考就肯定不会出错。当然,复杂的状态机可能会用多个always描述时序或组合,但是其基本思路是不变的。

京公网安备 11010502036488号