Exams/review2015 count1k
构建一个计数从 0 到 999(包括 0 到 999)的计数器,周期为 1000 个周期。复位输入是同步的,应将计数器复位为 0。
代码如下:
module top_module (
input clk,
input reset,
output reg [9:0] q);
//时序逻辑电路,必须是寄存器才能在里面赋值
always@(posedge clk)begin
if(reset)
q <= 10'd0;
else if(q == 10'd999)
q <= 10'd0;
else
q <= q + 1'd1;
end
endmodule
Exams/review2015 shiftcount
这是由几个较小的电路构建复杂计数器的五个练习系列中的第一个组件。看最后的练习为整体设计。
构建一个四位移位寄存器,该寄存器也可用作下降计数器。当shift_ena为 1 时,数据首先以最高有效位移动。当count_ena为 1 时,移位寄存器中的当前数字递减。由于整个系统永远不会同时使用shift_ena和count_ena,因此如果两个控制输入均为1,则电路的作用无关紧要(这主要意味着哪种情况具有更高的优先级并不重要)。
代码如下:
module top_module (
input clk,
input shift_ena,
input count_ena,
input data,
output reg [3:0] q);
always@(posedge clk)begin
//用case语句来描述,两个使能信号不能同时为1
//当shift为1时,以最高有效位移动,当count为1时,为下降计数器
case({shift_ena, count_ena})
2'b10:
q <= {q[2:0], data};
2'b01:
q <= q - 4'd1;
default:q <= q;
endcase
end
endmodule
Exams/review2015 fsmseq
这是由几个较小的电路构建复杂计数器的五个练习系列中的第二个组件。看最后的练习为整体设计。
构建一个有限状态机,用于在输入位流中搜索序列 1101。找到序列后,它应将start_shifting设置为 1,直到重置。卡在最终状态旨在模拟在尚未实现的更大 FSM 中前往其他状态。我们将在接下来的几个练习中扩展此 FSM。
代码如下:
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output start_shifting);
//状态定义,直接给定几个状态
parameter S0 = 3'd0, S1 = 3'd1, S2 = 3'd2,
S3 = 3'd3, S4 = 3'd4;
reg [2:0] state, next_state;
//时序逻辑,状态转换
always@(posedge clk)begin
if(reset)
state <= S0;
else
state <= next_state;
end
//组合逻辑,状态获取
always@(*)begin
case(state)
S0: next_state = data ? S1 : S0;//0
S1: next_state = data ? S2 : S0;//1
S2: next_state = data ? S2 : S3;//11
S3: next_state = data ? S4 : S0;//110
S4: next_state = S4;//1101
default: next_state = S0;
endcase
end
//组合逻辑输出
assign start_shifting = (state == S4);
endmodule
Exams/review2015 fsmshift
这是由五个练习组成的系列中的第三个组件,该练习由几个较小的电路构建一个复杂的计数器。看最后的练习为整体设计。
作为FSM的一部分,用于控制移位寄存器,我们希望能够在检测到正确的位模式时使移位寄存器正好启用4个时钟周期。我们在考试/review2015_fsmseq中处理序列检测,因此FSM的这一部分仅处理4个周期的移位寄存器启用。
每当重置 FSM 时,断言 shift_ena 4 个周期,然后永久断言 0(直到重置)。
代码如下:
module top_module (
input clk,
input reset, // Synchronous reset
output shift_ena);
//状态定义,直接给定几个状态
parameter S0 = 3'd0, S1 = 3'd1, S2 = 3'd2,
S3 = 3'd3, S4 = 3'd4;
reg [2:0] state, next_state;
//时序逻辑,状态转换
always@(posedge clk)begin
if(reset)
state <= S0;
else
state <= next_state;
end
//组合逻辑,状态获取
always@(*)begin
case(state)
//没有输入信号,所以把复位信号当做输入
//只有当连续出现4个低电平复位信号后shift_ena才会变为0
S0: next_state = reset ? S0 : S1;
S1: next_state = reset ? S0 : S2;
S2: next_state = reset ? S0 : S3;
S3: next_state = reset ? S0 : S4;
S4: next_state = S4;//永远为0
default: next_state = S0;
endcase
end
//组合逻辑输出
assign shift_ena = ~(state == S4);
endmodule
Exams/review2015 fsm
这是由几个较小的电路构建复杂计数器的五个练习系列中的第四个组件。看最后的练习为整体设计。
您可能希望先执行 FSM:启用移位寄存器和 FSM:序列识别器。
我们希望创建一个计时器:
在检测到特定模式 (1101) 时启动,
再移位 4 位以确定延迟的持续时间,
等待计数器完成计数,并且
通知用户并等待用户确认计时器。
在此问题中,仅实现控制计时器的有限状态机。此处不包括数据路径(计数器和一些比较器)。
串行数据在数据输入引脚上可用。当接收到模式1101时,状态机必须随后在4个时钟周期内断位输出shift_ena
之后,状态机断言其计数输出以指示它正在等待计数器,并等待输入done_counting为高。
此时,状态机必须断言完成以通知用户计时器已超时,并等待输入确认为 1,然后再复位以查找下一次出现的开始序列 (1101)。
状态机应复位到它开始搜索输入序列1101的状态。
下面是预期输入和输出的示例。“x”状态可能有点令人困惑。它们表明FSM不应该关心该周期中的特定输入信号。例如,一旦检测到 1101 模式,FSM 将不再查看数据输入,直到在完成其他所有操作后恢复搜索。
仿真图说明:首先系统没有启动,当有1101的数据输入时,系统进入一个工作状态,刚开始工作的时候又不是直接开始计时的,首先发出4个时钟的移位使能输出,接着发出counting信号进入计数状态,接着计数器等待外部给它一个结束完成计数信号,接着给外面一个done的完成接收的信号,给外面一个响应信号ack。
代码如下:
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 = 4'd0, S1 = 4'd1, S2 = 4'd2,
S3 = 4'd3, S4 = 4'd4, S5 = 4'd5, S6 = 4'd6, S7 = 4'd7,
COUNTING = 4'd8, DONE = 4'd9;
reg [3:0] state, next_state;
//时序逻辑,状态转换
always@(posedge clk)begin
if(reset)
state <= S0;
else
state <= next_state;
end
//组合逻辑,状态获取
always@(*)begin
case(state)
//说明:首先系统没有启动,当有1101的数据输入时,系统进入工作状态,
//刚开始工作的时候又不是直接开始计时的,首先发出4个时钟的移位使能输出,
//接着发出counting信号进入计数状态,接着计数器等待外部给它一个结束完成计数信号,
//接着给外面一个done的完成接收的信号,给外面一个响应信号ack
S0: next_state = data ? S1 : S0;
S1: next_state = data ? S2 : S0;
S2: next_state = data ? S2 : S3;
S3: next_state = data ? S4 : S0;
S4: next_state = reset ? S0 : S5;
S5: next_state = reset ? S0 : S6;
S6: next_state = reset ? S0 : S7;
S7: next_state = reset ? S0 : COUNTING;
COUNTING: next_state = done_counting ? DONE : COUNTING;
DONE: next_state = ack ? S0 : DONE;
default: next_state = S0;
endcase
end
//组合逻辑输出
assign shift_ena = (state == S4)|(state == S5)|(state == S6)|(state == S7);
assign counting = (state == COUNTING);
assign done = (state == DONE);
endmodule
Exams/review2015 fancytimer
这是由几个较小的电路构建复杂计数器的五个练习系列中的第五个组件。您可能希望先做前面的四个练习(计数器,序列识别器 FSM,密克罗尼西亚联邦延迟和组合式密克罗尼西亚联邦).
我们想创建一个带有一个输入的计时器:
在检测到特定输入模式 (1101) 时启动,
再移位 4 位以确定延迟的持续时间,
等待计数器完成计数,并且
通知用户并等待用户确认计时器。
串行数据在数据输入引脚上可用。当接收到模式1101时,电路必须移入接下来的4位,最高有效位在前。这 4 位决定了计时器延迟的持续时间。我将其称为延迟[3:0]。
之后,状态机断言其计数输出以指示它正在计数。状态机必须精确计算(延迟 [3:0] + 1)* 1000 个时钟周期。例如,delay=0 表示计数 1000 个周期,延迟=5 表示计数 6000 个周期。同时输出当前剩余时间。这应该等于 1000 个周期的延迟,然后 1000 个周期的延迟-1,依此类推,直到 1000 个周期为 0。当电路不计数时,count[3:0] 输出为 don't-care(任何便于实现的值)。
此时,电路必须断言完成以通知用户定时器已超时,并等到输入确认为1后再复位以查找下一次出现的开始序列(1101)。
电路应复位到开始搜索输入序列1101的状态。
下面是预期输入和输出的示例。“x”状态可能有点令人困惑。它们表明FSM不应该关心该周期中的特定输入信号。例如,一旦读取了1101和delay[3:0],电路将不再查看数据输入,直到在其他所有操作完成后恢复搜索。在本例中,电路计数2000个时钟周期,因为延迟[3:0]值为4'b0001。最后几个周期以延迟 [3:0] = 4'b1110 开始另一个计数,这将计数 15000 个周期。
代码如下:
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output [3:0] count,
output counting,
output done,
input ack );
//状态定义,直接给定几个状态
parameter S0 = 4'd0, S1 = 4'd1, S2 = 4'd2,
S3 = 4'd3, S4 = 4'd4, S5 = 4'd5, S6 = 4'd6, S7 = 4'd7,
COUNTING = 4'd8, DONE = 4'd9;
reg [3:0] state, next_state;
//时序逻辑,状态转换
always@(posedge clk)begin
if(reset)
state <= S0;
else
state <= next_state;
end
//组合逻辑,状态获取
always@(*)begin
case(state)
S0: next_state = data ? S1 : S0;
S1: next_state = data ? S2 : S0;
S2: next_state = data ? S2 : S3;
S3: next_state = data ? S4 : S0;
S4: next_state = reset ? S0 : S5;
S5: next_state = reset ? S0 : S6;
S6: next_state = reset ? S0 : S7;
S7: next_state = reset ? S0 : COUNTING;
COUNTING: next_state = done_counting ? DONE : COUNTING;
DONE: next_state = ack ? S0 : DONE;
default: next_state = S0;
endcase
end
//组合逻辑输出
wire shift_ena;
assign shift_ena = (state == S4)|(state == S5)|(state == S6)|(state == S7);
assign counting = (state == COUNTING);
assign done = (state == DONE);
//进行计数,并且知道计数计了多少
wire done_counting;
assign done_counting = ((count == 4'd0) && (cnt == 10'd0));
//count == delay
always@(posedge clk)begin
if(reset)
count <= 4'd0;
else if(shift_ena)
count <= {count[2:0], data};
else if(counting)
count <= (cnt == 10'd0) ? count - 4'd1 : count;
else
count <= count;
end
//count1000
reg [9:0] cnt;
always@(posedge clk)begin //COUNT
if(reset)
cnt <= 10'd999;
else if(counting)
cnt <= (cnt == 10'd0) ? 10'd999 : cnt - 10'd1;
else
cnt <= 10'd999;//1000
end
endmodule
Exams/review2015 fsmonehot
给定以下具有 3 个输入、3 个输出和 10 个状态的状态机:
假设使用以下单热编码,则通过检查推导出下一状态逻辑方程和输出逻辑方程:(S, S1, S11, S110, B0, B1, B2, B3, Count, Wait) = (10'b0000000001, 10'b0000000010, 10'b00000000100, ... , 10'b1000000000)
通过假设独热编码的检查来导出状态转换和输出逻辑方程。仅实现此状态机的状态转换逻辑和输出逻辑(组合逻辑部分)。(测试平台将使用非一个热输入进行测试,以确保您不会尝试做更复杂的事情。看 fsm3onehot用于描述“通过检查”推导单热状态机的逻辑方程的含义。
编写生成以下等式的代码:
*B3_next -- 状态 B3 的下一个状态逻辑
*S_next
*S1_next
*Count_next
*Wait_next
*done -- 输出逻辑
*counting
*shift_ena
代码如下:
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 = 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