概述
文章目录
- 1、Counter with period 1000
- 2、4-bit shift register and down counter(移位寄存器)
- 3、fsmseq 序列1101识别器
- 4、fsmshift 状态机启用移位寄存器
- 5、fsm (将移位寄存器和序列识别器进行结合)
- 6、fancytimer完整的计数器
- 7、fsmonehot 独热码
1、Counter with period 1000
上行1000的计数器
生成一个从 0 到 999(含 0)计数的计数器,周期为 1000 个周期。复位输入是同步的,应将计数器复位至0。
低电平有效,高电平复位。
module top_module (
input clk,
input reset,
output [9:0] q
);
always @ (posedge clk)
if(reset)
q <= 10'b0;
else if(q == 10'd999)
q <= 10'b0;
else
q <= q + 1'b1;
endmodule
2、4-bit shift register and down counter(移位寄存器)
构造一个四位移位寄存器,同时也能做下行计数器(10,9,8…)
当shift_ena为 1 时,数据data的高位先移动到移位寄存器。(暂存)
当前移位寄存器中的数字在count_ena为 1 时逐时钟的进行递减。
shift_ena和count_ena没有重要级先后顺序,因为他们不会同时使能。
由于递减,因此我们需要找到最大值,q为4位,8421,因此可表示的最大数为15
module top_module (
input clk,
input shift_ena,
input count_ena,
input data,
output [3:0] q
);
reg [3:0] q_temp;
always @ (posedge clk)begin
if(shift_ena == 1'b1)
q_temp <= {q[2:0],data};
else if(count_ena == 1'b1)begin
if(q_temp <= 4'd0)begin
q_temp <= 4'd15;
end
else
q_temp <= q_temp - 1'b1;
end
else
q_temp <= q_temp;
end
assign q = q_temp;
endmodule
3、fsmseq 序列1101识别器
构建一个有限状态机,用于在输入位流中搜索序列1101。
找到1101序列后,应将start_shifting设置为 1,直到重置。
由于检测序列1101,因此共设置五个状态:空闲状态和四位数值接收的四个状态。
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output start_shifting
);
parameter IDLE = 5'b00001;
parameter S1 = 5'b00010;
parameter S2 = 5'b00100;
parameter S3 = 5'b01000;
parameter S4 = 5'b10000;
reg [4:0] state,next_state;
//第一段,状态寄存器
always @ (posedge clk)
if(reset)
state <= IDLE;
else
state <= next_state;
//第二段,组合逻辑描述状态转移
always @ (*)begin
case(state)
IDLE : next_state = data ? S1 : IDLE;
S1 : next_state = data ? S2 : IDLE;
S2 : next_state = data ? S2 : S3;
S3 : next_state = data ? S4 : IDLE;
S4 : next_state = S4;
default: next_state = IDLE;
endcase
end
//第三段,组合逻辑描述输出
always@(*)
start_shifting = (state == S4);
endmodule
4、fsmshift 状态机启用移位寄存器
作为用于控制移位寄存器的FSM的一部分,我们希望能够在检测到正确的位模式时使能移位寄存器正好4个时钟周期。
我们在上一题fsmseq中已经完成了序列检测的处理,因此 FSM 的这一部分仅处理 4 个周期的移位寄存器启用。
当有限状态机被复位时,将shift_ena拉高4个周期,之后保持为0直到再次复位。
根据图可看出,复位是高的时候,输出也一直是高电平。
因此可以设置三个状态,空闲状态,使能拉高状态以及保持为0的状态。其中使能拉高状态下我们设计计数器来完成,拉高四个周期因此设计模4计数器。
module top_module (
input clk,
input reset, // Synchronous reset
output shift_ena
);
parameter IDLE = 3'b001;
parameter ENA = 3'b010;
parameter STOP = 3'b100;
reg [3:0] state,next_state;
reg [2:0] counter;
//第一段,状态寄存器
always @(posedge clk) begin
if(reset) begin
state <= IDLE;
end
else begin
state <= next_state;
end
end
//第二段,状态转移
always@(*)
case(state)
IDLE: next_state = ENA;
ENA : next_state = (counter == 3'd3 ) ? STOP : ENA;
STOP: next_state = STOP;
default: next_state = IDLE;
endcase
//第三段,描述输出
always@(*)
shift_ena = (state == ENA | state == IDLE);
//设计一个模4计数器
always @(posedge clk) begin
if(reset)
counter <= 3'd0;
else if(next_state == ENA) //因为采用的是时序逻辑,因此用次态
counter <= counter + 1'b1;
else
counter <= 3'd0;
end
endmodule
5、fsm (将移位寄存器和序列识别器进行结合)
题目理解:
空闲状态IDLE:主要是对复位初始状态,高电平复位,低电平开始进行序列的检测。
序列检测包括三个状态,S1,S11,S110。状态转移的条件是输入data ( 只要检测错误就要重新检测)
shift_ena抬高四个周期的状态:在序列接收成功后进入此状态,该状态包括ENA0-ENA3四个状态
计数状态:当输入done_counting为高电平的时候跳转到等待通知状态。否则一直计数
等待通知状态:当等待通知输入ack为1的时候,重置以查找下一个出现的启动序列,否则的话一直处于等待通知状态。
至此我们即可完成第一二段状态机。
同时以下三个信号是输出,在第三段状态机中描述。
output shift_ena,
output counting,
output done,
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output shift_ena,
output counting,
input done_counting,
output done,
input ack
);
//十个状态,这里就不采用独热码了
parameter IDLE = 4'd0;
parameter S1 = 4'd1;
parameter S11 = 4'd2;
parameter S110 = 4'd3;
parameter ENA0 = 4'd4;
parameter ENA1 = 4'd5;
parameter ENA2 = 4'd6;
parameter ENA3 = 4'd7;
parameter COUNT = 4'd8;
parameter WAIT = 4'd9;
reg [3:0] state,next_state;
//第一段,状态寄存器
always@(posedge clk)
if(reset)
state <= IDLE;
else
state <= next_state;
//第二段,状态转移
always@(*)
case(state)
IDLE :next_state = data ? S1 : IDLE;
S1 :next_state = data ? S11 : IDLE;
S11 :next_state = data ? S11 : S110;
S110 :next_state = data ? ENA0 : IDLE;
ENA0 :next_state = ENA1;
ENA1 :next_state = ENA2;
ENA2 :next_state = ENA3;
ENA3 :next_state = COUNT;
COUNT :next_state = done_counting ? WAIT : COUNT;
WAIT :next_state = ack? IDLE : WAIT;
default: next_state = IDLE;
endcase
//第三段,描述输出
always @ (posedge clk )begin
if(reset)begin
shift_ena <= 1'b0;
counting <= 1'b0;
done <= 1'b0;
end
else
case(next_state)
IDLE,S1,S11,S110:begin
shift_ena <= 1'b0;
counting <= 1'b0;
done <= 1'b0;
end
ENA0,ENA1,ENA2,ENA3:begin
shift_ena <= 1'b1;
counting <= 1'b0;
done <= 1'b0;
end
COUNT:begin
shift_ena <= 1'b0;
counting <= 1'b1;
done <= 1'b0;
end
WAIT:begin
shift_ena <= 1'b0;
counting <= 1'b0;
done <= 1'b1;
end
default:begin
shift_ena <= 1'b0;
counting <= 1'b0;
done <= 1'b0;
end
endcase
end
endmodule
6、fancytimer完整的计数器
该题目是前面四个题目的结合。
有四个状态是移位拉高四个周期的状态,上题中我们这里没有其他的操作,只是拉高四位,二本题目需要进行四位的移位,首先是最高有效位。同时这 4 位决定了计时器延迟的持续时间(计数器的计数周期)。我将其称为delay延迟[3:0]。 ——可表示的最大数是15
增加计数器状态,来给予精确的计数,计数周期为(delay[3:0] + 1 )* 1000 个时钟周期,比如 delay = 0 时,计数值为 1000 个周期。delay = 5 代表 6000 个周期。输出count表示当前剩余的计数周期(计数的千位数),这就应该等于1000个周期的延迟,比如说还剩1000周期,那么输出1,还剩999个周期,输出0,还剩15000个周期,输出15,当计数停止后,count可输出任意数。
当计数完成后,done 信号置为高电平,通知上层应用计数器计数完成。
后等待 ack 信号,当该信号置高后,状态机清除 done 信号,返回空闲状态等待重新捕获下一个 1101 序列,否则一直处于等待状态,等ack高电平的到来。
上图中斜线表示当前信号为X,也就是状态机不关心的值(省略),如图存在序列1101,同时在延迟了四个周期后,开始计数,同时counting置为了1。可看出电路计数周期是2000,因此delay为1,所以 delay[3:0] 数值为 4’b0001 。在后续的第二个计数周期中,count能看出是e,计数周期是15000.
module top_module (
input clk,
input reset,
input data,
input ack,
output [3:0] count,
output counting,
output done
);
parameter S = 4'd0;
parameter S1 = 4'd1;
parameter S11 = 4'd2;
parameter S110 = 4'd3;
parameter DELAY = 4'd4;
parameter COUNT = 4'd5;
parameter WAIT = 4'd6;
reg [3:0] cur_state ;
reg [3:0] next_state ;
reg [1:0] cnt_delay ; //用来接收序列流的计数器
reg [15:0] cnt ;
reg [3:0] delay ;
//第一段同步时序描述状态转移
always @(posedge clk)begin
if(reset)
cur_state <= S;
else
cur_state <= next_state;
end
//第二段采用组合逻辑,并根据状态转移条件来描述状态转移规律
always@(*)begin
case(cur_state)
S : next_state = data ? S1 :S;
S1 : next_state = data ? S11 :S;
S11 : next_state = data ? S11 :S110;
S110 : next_state = data ? DELAY :S;
DELAY:
if(cnt_delay == 2'd3)
next_state = COUNT;
else
next_state = DELAY;
COUNT:
if(cnt == 16'd0)
next_state = WAIT;
else
next_state = COUNT;
WAIT :
if(ack)
next_state = S;
else
next_state = WAIT;
default: next_state = S;
endcase
end
//第三段,组合逻辑描述描述输出
always@(*)begin
count = cnt/1000; //用来输出千位
counting = (cur_state == COUNT);
done = (cur_state == WAIT);
end
//延时计数器,计数4个时钟,来接收delay数据
always @(posedge clk)begin
if(reset)
cnt_delay <= 2'd0;
else if(cur_state == DELAY)begin
cnt_delay <= cnt_delay + 1'b1;
end
else
cnt_delay <= cnt_delay;
end
//根据接收到的delay数据进行计数周期的运算
always @(posedge clk)begin
if(reset)
cnt <= 16'd0;
else if(cur_state == DELAY)
cnt <= (delay+1'b1) * 1000-1'd1;
else if(cur_state == COUNT)
cnt <= cnt - 1'd1;
else
cnt <= cnt;
end
//接收delay 的四位数据以计算计数周期,根据每一位的delay计算出十进制数,然后套用计数周期计算公式
//delay为0001,则在上面代入公式计算出cnt=1999
always@(*)begin
if(cur_state == DELAY)
case(cnt_delay)
2'd0: delay[3] = data;
2'd1: delay[2] = data;
2'd2: delay[1] = data;
2'd3: delay[0] = data;
default:;
endcase
else
delay = 4'b0000;
end
endmodule
7、fsmonehot 独热码
该题给出了如果的状态转移图,然后采用独热码的方式来编写组合逻辑部分(状态转移以及输出。)
module top_module(
input d,
input done_counting,
input ack,
input [9:0] state, // 10-bit one-hot current state
output B3_next,
output S_next,
output S1_next,
output Count_next,
output Wait_next,
output done,
output counting,
output shift_ena
); //
parameter S=0, S1=1, S11=2, S110=3, B0=4, B1=5, B2=6, B3=7, Count=8, Wait=9;
assign B3_next = state[B2];
assign S_next = ~d & state[S] | ~d & state[S1] | ~d & state[S110] | ack & state[Wait];
assign S1_next = d & state[S];
assign Count_next = state[B3] | ~done_counting & state[Count];
assign Wait_next = done_counting & state[Count] | ~ack & state[Wait];
assign done = state[Wait];
assign counting = state[Count];
assign shift_ena = state[B0] | state[B1] | state[B2] |state[B3];
endmodule
最后
以上就是忧郁口红为你收集整理的HDLBits(十 三)学习笔记——Building Lager Circuits (1000计数器 —— FSM:One-hot logic equations独热码)1、Counter with period 10002、4-bit shift register and down counter(移位寄存器)3、fsmseq 序列1101识别器4、fsmshift 状态机启用移位寄存器5、fsm (将移位寄存器和序列识别器进行结合)6、fancytimer完整的计数器7、fsmonehot 的全部内容,希望文章能够帮你解决HDLBits(十 三)学习笔记——Building Lager Circuits (1000计数器 —— FSM:One-hot logic equations独热码)1、Counter with period 10002、4-bit shift register and down counter(移位寄存器)3、fsmseq 序列1101识别器4、fsmshift 状态机启用移位寄存器5、fsm (将移位寄存器和序列识别器进行结合)6、fancytimer完整的计数器7、fsmonehot 所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复