3.3.1 Counter with period 1000
问题陈述:
建立一个从0到999的计数器,包括0到999,周期为1000个周期。复位输入是同步的,应将计数器复位0.
Verilog代码:
module top_module (
input clk,
input reset,
output [9:0] q);
always @(posedge clk)
begin
if(reset)
q<=0;
else if(q==999)
q<=0;
else
q<=q+1'b1;
end
endmodule
3.3.2 4-bit shift register and down counter
问题陈述:
构建一个四位移位寄存器,该寄存器也用作递减计数器。当shift_ena为1时,数据首先移入最高有效位。当count_ena为1时当前在移位寄存器中的数字递减。由于整个系统不会同时使用shift_ena和counter_ena,因此您的电路无关紧要如果两个控制输入都为1(这主要意味着,哪种情况获得更高优先级并不重要)。
Verilog代码:
module top_module (
input clk,
input shift_ena,
input count_ena,
input data,
output [3:0] q);
always@(posedge clk)
begin
if(shift_ena)
begin
q[0]<=data;
q[1]<=q[0];
q[2]<=q[1];
q[3]<=q[2];
end
else if(count_ena)
q[3:0]<=q[3:0]-1'b1;
else
q<=q;
end
endmodule
3.3.3 FSM:Sequence 1101 recognizer
问题陈述:
构建一个有限状态机,在输入比特流中搜索序列1101.找到序列后,应将start_shifting设置为1,直到重置。陷入最终状态旨在模拟在尚未实现的更大FSM中进入其他状态。我们将在接下来的几个练习中扩展这个FSM。
Verilog代码:
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output start_shifting);
parameter s0=0,s1=1,s2=2,s3=3,s4=4,END=5;
reg[3:0]state,next;
always@(posedge clk)
begin
if(reset)
state<=s0;
else
state<=next;
end
always@(*)
begin
case(state)
s0:next=data?s1:s0;
s1:next=data?s2:s0;
s2:next=data?s2:s3;
s3:next=data?s4:s0;
s4:next=s4;
default:next=s0;
endcase
end
always@(posedge clk)
begin
if(reset)
start_shifting<=1'b0;
else if(next==s4)
start_shifting<=1'b1;
end
endmodule
3.3.4 FSM:Enable shift register
问题陈述:
作为用于控制移位寄存器的FSM的一部分,我们希望能够在检测到正确的位模式的移位寄存器恰好4个周期。FSM的这一部分仅处理启用4个周期的移位寄存器。
Verilog代码:
module top_module (
input clk,
input reset, // Synchronous reset
output shift_ena);
reg[3:0] counter;
always@(posedge clk)
begin
if(reset)
counter<=4'd0;
else if(shift_ena)
begin
if(counter==4'd3)
counter<=4'd0;
else
counter<=counter+1'b1;
end
end
always@(posedge clk)
begin
if(reset)
shift_ena<=1'b1;
else if((shift_ena==1'b1)&&(counter==4'd3))begin
shift_ena<=1'b0;
end
end
endmodule
3.3.5 FSM:The complete FSM
问题陈述:
我们想创建一个带有输入的计时器:
1.在检测到特定模式(1101)时启动
2.再平移4位来决定延迟的时间,
3.等计数器数完,然后
4.通知用户并等待用户确认计时器。在这个问题中,只实现控制计时器的有限状态机。此处不包括数据路径(计数器和一些比较器)。
串行数据在数据输入引脚上可用。当接收到模式1101时,状态机必须在4个时钟周期内断言输出shift_ena。在此之后,状态机断言其计数输出,以指示它正在等待计数器,并等待直到输入done_counting为高值。
此时,状态机必须断言done以通知用户计时器已超时,并等待直到输入ack为1,然后重置以查找开始序列(1101)的下一个出现。
状态机应该重置为开始搜索输入序列1101的状态。
下面是预期输入和输出的示例。“x”状态可能读起来有点混乱。它们表明FSM不应该关心该周期中特定的输入信号。例如,一旦检测到1101模式,FSM就不再查看数据输入,直到完成所有其他工作后才恢复搜索。
Verilog代码:
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output shift_ena,
output counting,
input done_counting,
output done,
input ack );
parameter s0=0,s1=1,s2=2,s3=3,s4=4,b1=5,b2=6,b3=7,counter=8,WAIT_T=9;
reg[3:0]state,next;
always@(posedge clk)
begin
if(reset)
state<=s0;
else
state<=next;
end
always@(*)
begin
case(state)
s0:next=data?s1:s0;
s1:next=data?s2:s0;
s2:next=data?s2:s3;
s3:next=data?s4:s0;
s4:next=b1;
b1:next=b2;
b2:next=b3;
b3:next=counter;
counter:next=done_counting?WAIT_T:counter;
WAIT_T:next=ack?s0:WAIT_T;
endcase
end
assign shift_ena=((state==s4)||(state==b1)||(state==b2)||(state==b3));
assign counting=(state==counter);
assign done=(state==WAIT_T);
endmodule
3.3.6 The complete timer
问题陈述:
我们想创建一个带有一个输入的计时器:
1.当检测到特定输入模式 (1101) 时启动
2.再移 4 位以确定延迟的持续时间
3.等待计数器完成计数
4.并且 通知用户并等待用户确认计时器。
串行数据在数据输入引脚上可用。当接收到模式1101时,电路必须移位接下来的4位,首先最高有效位。这4位决定了定时器延迟的持续时间。将此称为delay[3:0]。
之后,状态机断言其计数输出,以指示它正在计数。状态机必须精确计算(delay[3:0]+ 1)* 1000个时钟周期。例如,delay=0表示计数1000个循环,delay=5表示计数6000个周期。同时输出当前剩余时间。这应该等于1000个周期的延迟,然后1000个周期的延迟-1,以此类推,1000个周期的延迟是0。当电路不计数时,count[3:0]输出是不关心的(任何值对你来说是方便实现的)。
此时,电路必须断言done来通知用户计时器已经超时,并等待直到输入ack为1,然后重置以寻找开始序列(1101)的下一个出现。
电路应该重置到开始搜索输入序列1101的状态。
下面是预期输入和输出的示例。“x”状态可能读起来有点混乱。它们表明FSM不应该关心该周期中特定的输入信号。例如,一旦读取了1101和delay[3:0],电路就不再查看输入的数据,直到在所有其他事情都完成后才恢复搜索。在本例中,电路计数为2000个时钟周期,因为delay[3:0]值为4’b0001。最后几个循环开始另一个计数,延迟[3:0]= 4’b1110,这将计数15000个循环。
Verilog代码:
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output [3:0] count,
output counting,
output done,
input ack );
parameter IDLE=4'd0,s1=4'd1,s11=4'd2,s110=4'd3,b0=4'd4,b1=4'd5,b2=4'd6,b3=4'd7,Count=4'd8,WAIT=4'd9;
reg[3:0] state,next;
reg[3:0] delay;
reg[15:0]counter;
reg[3:0]temp;
wire done_counting;
always@(posedge clk)begin
if(reset) begin
state<=IDLE;
end
else
state<=next;
end
always@(posedge clk) begin
if(reset)
counter<=16'd0;
else if(next==WAIT)
counter<=16'd0;
else if(next==Count)
counter<=counter+1'b1;
end
always @(*) begin
if(counter<=16'd1000)
temp=4'd0;
else if(counter==16'd2000)
temp=4'd1;
else if(counter==16'd3000)
temp=4'd2;
else if(counter==16'd4000)
temp=4'd3;
else if(counter==16'd5000)
temp=4'd4;
else if(counter==16'd6000)
temp=4'd5;
else if(counter==16'd7000)
temp=4'd6;
else if(counter==16'd8000)
temp=4'd7;
else if(counter==16'd9000)
temp=4'd8;
else if(counter==16'd10000)
temp=4'd9;
else if(counter==16'd11000)
temp=4'd10;
else if(counter==16'd12000)
temp=4'd11;
else if(counter==16'd13000)
temp=4'd12;
else if(counter==16'd14000)
temp=4'd13;
else if(counter==16'd15000)
temp=4'd14;
else
temp=4'd15;
end
assign done_counting=((state==Count)&(counter==(delay+1)*1000))?1'b1:1'b0;
always@(*) begin
case(state)
IDLE: next=data? s1:IDLE;
s1 : next=data? s11:IDLE;
s11 : next=data? s11:s110;
s110: next=data? b0:IDLE;
b0 : begin
next=b1; delay[3]=data;
end
b1: begin
next=b2; delay[2]=data;
end
b2: begin
next=b3; delay[1]=data;
end
b3:begin
next=Count; delay[0]=data;
end
Count:next=done_counting?WAIT:Count;
WAIT :next=ack?IDLE:WAIT;
endcase
end
assign count=(state==Count)?(delay-temp):4'd0;
assign counting=(state==Count);
assign done=(state==WAIT);
endmodule
3.3.7 FSM: One-hot logic equation
问题陈述:
给定一下具有3个输入、3个输出、10个状态的状态机:
假设使用以下one-hot编码,通过检查导出下一个状态逻辑方程好人输出逻辑方程:(S, S1, S11, S110, B0, B1, B2, B3, Count, Wait) = (10’b0000000001, 10’b0000000010, 10’b0000000100, … , 10’b1000000000)
假设one-hot编码,通过检查导出状态转换和输出逻辑方程。仅实现此状态机的状态转换和输出逻辑方程。仅实现此状态转换(组合逻辑部分)。(测试台将使用非一个热输入进行测试,以确保您不会尝试复杂的事情)。
编写上次以下等式代码:
- List item
- B3_next – next-state logic for state B3
- S_next
- S1_next
- Count_next
- Wait_next
- done – output logic
- counting
Verilog代码:
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
); //
// You may use these parameters to access state bits using e.g., state[B2] instead of state[6].
parameter S=0, S1=1, S11=2, S110=3, B0=4, B1=5, B2=6, B3=7, Count=8, Wait=9;
// assign B3_next = ...;
// assign S_next = ...;
// etc.
assign B3_next=(state[B2]);
assign S_next=(~d&(state[S]|state[S1]|state[S110])|(ack&state[Wait]));
assign S1_next=(d&state[S]);
assign Count_next=(state[B3]|(state[Count]&~done_counting));
assign Wait_next=((state[Count]&done_counting)|(state[Wait]&~ack));
assign counting=(state[Count]);
assign done=(state[Wait]);
assign shift_ena=(state[B0]|state[B1]|state[B2]|state[B3]);
endmodule