时序电路设计
状态图描述
module checker(Z, X, clk);
parameter s0 = 2'b00, s1 = 2'b01, s2 = 2'b11, s3 = 2'b10;
output Z;
input X, clk;
reg [1:0] state, next_state;
reg Z;
always @(X, state)
case (state)
s0:if(X)
begin
next_state <= s1; Z = 0;
end
else
begin
next_state <= s0; Z = 0;
end
s1:if(X)
begin
next_state <= s2; Z = 0;
end
else
begin
next_state <= s0; Z = 0;
end
s2:if(X)
begin
next_state <= s3; Z = 1;
end
else
begin
next_state <= s0; Z = 0;
end
s3:if(X)
begin
next_state <= s3; Z = 1;
end
else
begin
next_state <= s0; Z = 0;
end
endcase
always @(posedge clk)
state <= next_state;
endmodule
化简描述
//序列检测器模块
module test (Z, X, clk);
output Z;
input X, clk;
wire w1, w2;
DFF U1 (.clk(clk), .D(X), .Q(w1));
DFF U2 (.clk(clk), .D(w1), .Q(w2));
assign Z = X & w1 & w2;
endmodule
//D触发器模块
module DFF (Q, D, clk);
output Q;
input D, clk;
reg Q;
always @(posedge clk) Q <= D;
endmodule
抽象描述方式
module checker (Z, X, clk);
output Z;
input X, clk;
reg [2:0] q;
reg Z;
always @(posedge clk) q<= {q[1:0], X};
always @(posedge clk)
if(q==3'b111) Z=1;
else Z = 0;
endmodule
触发器
最简D触发器
module DFF(q, clk, data_in);
output q;
input clk, data_in;
reg q;
always @(posedge clk) q <= data_in;
endmodule
带复位端的D触发器
module DFF_rst (q, clk, reset, data_in);
output q;
input clk, reset, data_in;
reg q;
always @(posedge clk)
if (!reset) q <= 0;
else q <= data_in;
endmodule
复杂功能的D触发器
module DFF_l(q, clk, resetl, reset2, data_in);
output q;
input clk, reset1, reset2, data_in;
reg q;
always @(posedge clk)
if (!reset1) q <= 0;
else q <= data_in;
always @(posedge clk or negedge reset2)
if (!reset2) q <= 0;
else q <= data_in;
endmodule
T触发器
module TFF(data_out, T, clk, reset);
output data_out;
input T, clk, reset;
reg data_out;
always @(posedge clk or negedge reset)
if (!reset) data_out <= 1'b0;
else if (T) data_out <= ~data_out;
endmodule
计数器
二进制计数器
module comp2bit (Q, clk, reset);
output Q;
input clk, reset;
reg Q;
always @ (posedge clk or negedge reset)
if (!reset)
Q<= 1'b0;
else
Q <= ~Q;
endmoduld
任意进制计数器
对于M进制的计数器,首先应确定计数器所需触发器的个数。N个触发器对应了 2^n
个状态,应有2^n>M。任意进制计数器选取满足条件的最小N, N为计数器中触发器的个数。
以十一进制计数器为例,最少需要4个触发器。
module comp_11 (count, clk, reset);
output [3:0] count;
input clk, reset;
reg [3:0] count;
always @ (posedge clk)
if(reset) count <= 4'b0000;
else
if (count == 4'b1010)
count <= 4'b0000;
else
count <= count+1;
endmodule
移位寄存器
环形移位寄存器
module shiftregistl(D, clk, reset);
parameter shiftregist_width = 4;
output [shiftregist_width-1:0] D;
input clk, reset;
reg [shiftregist_width-1:0] D;
always @(posedge clk)
if (!reset)
D <= 4'b0000;
else
D <= {D[shiftregist_width-2:0], D[shiftregist_width-1]};
endmodule
序列信号发生器
由移位寄存器构成
module signal_maker(out, clk, load, D);
parameter M = 6;
output out;
input clk, load;
input [M-1:0] D;
reg [M-1:0] Q;
initial Q = 6'b100111;
always @(posedge clk)
if (load) Q <= D;
else Q <= {Q[M-2:0], Q[M-1]};
assign out = Q[M-1];
endmodule
由移位寄存器和组合逻辑电路构成
首先确定所需移位寄存器的个数n。因M = 6,故 n>=3。其次确定移位寄存器的6个独立状态。按照移位规律每三位一组,划分6个状态为 100、001、011、111, 111、110。其中状态111重复出现,故取n = 4,并重新划分状态, 得到1001、0011、0111、1111、1110、1100。因此确定n = 4。第三,列态序表和反馈激励函数表,求反馈函数F的表达式。
F= ~Q3 + ~Q1 • ~Q0 +Q3+~Q2
module signal_maker(out, clk, load, D);
parameter M = 4;
output out;
input clk, load;
input [M-1 :0] D;
reg [M-1:0] Q;
wire w1;
always @(posedge clk) //时序电路部分,移位寄存器
if (load) Q<=D;
else Q <= {Q[M-2:0], w1};
assign w1 =(~Q[3])|(~Q[1]&(~Q[0]))|(Q[3]&(~Q[2])); //组合逻辑电路,反馈网络
assign out =Q[M-1];
endmodule
由计数器构成
module signal_maker(out, clk, reset);
parameter M = 3;
output out;
input clk, reset;
reg [M-l:0] counter;
always @(posedge clk)
if (!reset) counter <= 3'b000;
else counter <= counter+1;
assign out = counter[2]|((~counter[1])&(~counter[0]))l(counter[1]&counter[0]);
endmodule
有限同步状态机
Mealy型状态机的输出与当前状态和输入有关
Moore型状态机的输出仅依赖于当前状态, 而与输入无关
状态机的编码方式:
- 二进制编码:其状态寄存器是由触发器组成的。
- 格雷编码:格雷编码状态跳转时只有一个bit(位)发生变化,减少了产生毛刺和一些暂态的可能。
- 一位独热编码:这是对于n个状态采用n个bit(位)来编码,每个状态编码中只有一个bit(位)为1,如0001、0010、0100、1000。
状态机的两段式描述方法:
//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
always @(posedge clk or negedge rst_n) //异步复位
if(!rst_n) current_state <= IDLE;
else current_state <= next_state; //注意,使用的是非阻塞赋值
//第二个进程,组合逻辑 always模块,描述状态转移条件判断
always @(current_state or 输入信号) //电平触发
begin
next_state = x; //要初始化,使得系统复位后能进入正确的状态
case(current_state)
Sl:if(...)
next_state = S2; //阻塞赋值
outl <= 1'bl; //注意是非阻塞逻辑
...
endcase
end
状态机的三段式描述方法:
//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
always @(posedge clk or negedge rst_n) //异步复位
if(!rst_n) current_state <= IDLE;
else current_state <= next_state; //注意,使用的是非阻塞赋值
//第二个进程,组合逻辑always模块,描述状态转移条件判断
always @(current_state or 输入信号) //电平触发
begin
next_state = x; //要初始化,使得系统复位后能进入正确的状态
case(current_state)
S1: if(...)
next_state = S2; //阻塞赋值
...
endcase
end
//第三个进程,同步时序always模块,格式化描述次态寄存器输出
always @ (posedge clk or negedge rst_n)
begin
...//初始化
case(next_state or 输入信号)
S1:
outl <= 1'bl; //注意是非阻塞逻辑
S2:
outl <= 1'b0;
default:... //default的作用是免除综合工具综合出锁存器
endcase
end
4位顺序脉冲发生器
module state4(OUT, clk, rst_n);
output [3:0] OUT:
input clk;
input rst_n;
reg [3:0] OUT;
reg [1:0] STATE, next_STATE;
always @(STATE)
case (STATE)
2'b00:
begin
OUT <= 4'b11000;
next_STATE <= 2'b01;
2'b01:
begin
OUT <= 4'b0100;
next_STATE <= 2'b10;
end
2'b10:
begin
OUT<= 4'b0010;
next_STATE <= 2'b11;
end
2'bll:
begin
OUT <= 4'b0001;
next_STATE <= 2'b00;
end
endcase
always @(posedge clk or negedge rst_n)
if(!rst_n) STATE <= 2'b00:
else STATE <= next_STATE;
endmodule
自动售报机
module auto_sellor(current_state, data_out,
data_out_return1, data_out_return2, clk,
rst_n, data_in);
parameter state_width = 3, data_in_width = 3;
output [state_width-1:0] current_state;
output data_out, data_out_return1,
data_out_return2;
input [dala_in_width-1:O] data_in;
input clk, rst_n;
reg [state_width-l:OJ current_state, next_state;
reg data_out, data_out_returnl, data_out_return2;
always @(current_state or data_in)
case (current_state)
3'b000: case (data_in)
3'b000: begin
next_state <= 3'b000;
data_out <= 1'b0;
data_out_return1 <= 1'b0;
data_out_return2 <= 1'b0;
end
3'b001: begin
next_state <= 3'b001;
data_out <= 1'bO;
data_out_return 1 <= 1'bO;
data_out_retum2 <= 1'bO;
end
3'b010: begin
next_state <= 3'b010;
data_out <= 1'b0;
data_out_return1 <= 1'b0;
data_out_return2 <= 1'b0;
end
3'b011: begin
next_state <= 3'bl01;
data_out <= 1'bO;
data_out_return 1 <= 1'bO;
data_out_retum2 <= 1'bO;
end
3'bl00: begin
next_state <= 3'bOOO;
data_out <= 1'bl;
data_out_retum1 <= 1'bO;
data_out_retum2 <= 1'bl;
end
endcase
3'b001: case (data_in)
3'b000: begin
next_state <= 3'b001;
data_out <= 1'b0;
data_out_retum1 <= 1'b0;
data_out_retum2 <= 1'b0;
end
3'b001: begin
next_state <= 3'b010;
data_out <= 1'b0;
data_out_return1 <= 1'b0:
data_out_return2 <= 1'b0;
end
3'b010: begin
nexl_state <= 3'b011;
data_out <= 1'b0;
data_oul_return1 <= 1'b0;
data_out_return2 <= 1'b0:
end
3'b011: begin
next_state <= 3'b110;
data_out <= 1'b0;
data_out_return1 <= 1'b0;
data_out_return2 <= 1'b0:
end
endcase
3'b010: case (daia_in)
3'b000: begin
next_state <= 3'b010;
data_out <= 1'b0;
data_out_returnl <= 1'b0;
data_out_return2 <= 1'b0;
end
3'bOO1: begin
next_state <= 3'b011;
data_out <= 1'b0;
data_out_return1 <= 1'b0;
data_oul_return2 <= 1'b0;
end
3'b010: begin
next_state <= 3'b100;
data_out <= 1'b0;
data_out_return1 <= 1'b0;
data_out_return2 <= 1'b0;
end
3'b011: begin
next_state <= 3'b111;
data_out <= 1'b0;
data_out_return1 <= 1'b0;
data_out_return2 <= 1'b0;
end
endcase
3'bO11: case (data_in)
3'b000: begin
next_state <= 3'b011;
data_out <= 1'b0;
data_out_retuml <= 1'b0;
data_out_return2 <= 1'b0;
end
3'b001: begin
next_state <= 3'b100;
data_out <= 1'b0;
data_out_return1 <= 1'b0;
data_out_return2 <= 1'b0;
end
3'b010: begin
next_state <= 3'b101;
data_out <= 1'b0;
data_out_return1 <= 1'b0;
data_out_return2 <= 1'b0;
end
3'b011: begin
next_state <= 3'b000;
data_out <= 1'b1;
data_out_returnl <= 1'b0;
data_out_return2 <= 1'b0;
end
endcase
3'blOO: case (data_in)
3'bOOO: begin
next_state <= 3'b000;
data_out <= 1'b0;
data_out_return1 <= 1'b0;
data_out_return2 <= 1'b0;
end
31)001: begin
next_state <= 3'b101;
data_out <= 1'b0;
data_out_return1 <= 1'b0;
data_out_return2 <= 1'b0;
end
3'b010: begin
next_state <= 3'b110;
data_out <= 1'b0;
data_oul_return1 <= 1'b0;
data_out_retumrn2 <= 1'b0;
end
3'b011: begin
next_state <= 3'b000;
data_out <= 1'b1;
data_out_return1 <= 1'b1;
data_out_return2 <= 1'b0;
end
endcase
3'b101: case (data_in)
3'bOOO: begin
next_state <= 3'b101;
data_out <= 1'b0;
data_out_retuml <= 1'b0;
data_out_retum2 <= 1'b0;
end
3'bOO1: begin
next_state <= 3'b110;
data_out <= 1'b0;
data_out_return1 <= 1'b0;
data_out_return2 <= 1'b0;
end
3'b010: begin
next_state v= 3'bl 11;
data_out <= 1'bO;
data_out_retum1 <= 1'bO;
data_out_retum2 <= 1'bO;
end
3'bO11: begin
next_state <= 3'b000;
data_out <= 1'b1;
data_out_return1 <= 1'b0;
data_out_return2 <= 1'b1;
end
endcase
3'b110: case (data_in)
3'b000: begin
next_state <= 3'b110:
data_out <= 1'b0;
data_out_return1 <= 1'b0;
data_out_relurn2 <= 1'b0:
end
3'b001: begin
next_state <= 3'b111;
data_out <= 1'b0;
data_out_relurnl <= 1'bO:
data_out_return2 <= 1'bO;
end
3'b010: begin
next_state <= 3'bOOO;
data_out <= 1'b1;
data_out_return1 <= 1'bO;
data_out_return2 <= 1'bO;
end
endcase
3'b111: case (data_in)
3'bOOO: begin
next_state <= 3'b111;
data_out <= 1'b0;
data_oul_return 1 <= 1'b0;
data_out_retum2 <= 1'b0;
end
3'bOO1: begin
next_state <= 3'b000;
data_out <= 1'b1;
data_out_retum 1 <= 1'b0;
data_out_return2 <= 1'b0;
end
endcase
endcase
always @(posedge clk or rst_n)
if(!rst_n)
current_state <= 3'bOOO;
else
current_state <= next_state;
endmodule
“11010”序列检测器
module seqdet (D_out, D_in, rst_n, clk);
parameter IDLE = 3'd0, A = 3'd1,B = 3'd2, C = 3'd3, D = 3'd4, E = 3'd5;
output D_out;
input D_in, rst_n, clk;
reg [2:0] state, next_state;
wire D_out;
assign D_out = (state == E)? 1:0;
always @(state or D_in)
case (state)
IDLE : if(D_in) next_state = A;
else next_state = IDLE;
A : if(D_in) next_state = B;
else next_state = IDLE;
B : if(D_in) next_state = B;
else next_state = C;
C : if (D_in) next_state = D;
else next_state = IDLE;
D : if (D_in) next_state = B;
else next_state = E;
E : if (D_in) next_state = IDLE;
else next_state = A;
default: next_state = IDLE;
endcase
always @(posedge clk)
state <= next_state;
endmodule