前言
-
之前的文章《如何学习verilog,如何快速入门?》中提到了verilog学习,推荐了一个可以练习的网站:hdlbits网站,那自己也玩玩这个网站。
-
这篇文章,是接着《verilog练习:hdlbits网站上的做题笔记(6)》写的!
3.3 Building Larger Circuits
3.3.1 Counter with period 1000(Exams/review2015 count1k)
module top_module (
input clk,
input reset,
output [9:0] q);
always@(posedge clk)
if(reset)
q<=0;
else if(q >='d999)
q <= 'd0;
else
q <= q+'d1;
endmodule
3.3.2 4-bit shift register and down counter(Exams/review2015 shiftcount)
module top_module (
input clk,
input shift_ena,
input count_ena,
input data,
output [3:0] q);
always@(posedge clk)
if(shift_ena)
q<={q[2:0],data};
else if(count_ena)
q<=q-1'b1;
else
q<=q;
endmodule
3.3.3 FSM: Sequence 1101 recognizer(Exams/review2015 fsmseq)
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;
reg [2:0]state,next;
always@(posedge clk)
if(reset)
state <= S0;
else
state <= next;
always@(*)
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
always@(posedge clk)
if(reset)
start_shifting <= 0;
else if(next==S4) //注意此处的状态是next;
start_shifting <= 1;
endmodule
3.3.4 FSM: Enable shift register(Exams/review2015 fsmshift)
//方法1,状态机思想
module top_module (
input clk,
input reset, // Synchronous reset
output shift_ena);
parameter S0=0,S1=1,S2=2,S3=3,S4=4;
reg [2:0]state,next;
always@(posedge clk)
if(reset)
state <= S0;
else
state <= next;
always@(*)
case(state)
S0:next=S1;
S1:next=S2;
S2:next=S3;
S3:next=S4;
S4:next=S4;
default:next=S0;
endcase
assign shift_ena=(state==S0|state==S1|state==S2|state==S3);
endmodule
//第二种做法,计数器
module top_module (
input clk,
input reset, // Synchronous reset
output shift_ena);
reg [9:0] cnt_4;
//cnt_4(4次计数器)
always@(posedge clk)
if(reset)
cnt_4 <= 'd0;
else
cnt_4 <= cnt_4 + 1'b1;
assign shift_ena = cnt_4 < 'd4;
endmodule
//第三种做法:强烈推荐这种,理解计数器什么时候加,什么时候结束加!(我记得明德扬之前讲,经常是这种思路)
module top_module (
input clk,
input reset, // Synchronous reset
output shift_ena);
reg [9:0] cnt_4;//cnt_4(4次计数器)
wire cnt_end;
always@(posedge clk)
if(reset)
cnt_4 <= 'd0;
else if(shift_ena)
cnt_4 <= cnt_4 + 1'b1;
else
cnt_4 <= 'd0;
assign cnt_end = shift_ena && (cnt_4 == 'd3);
always@(posedge clk)
if(reset)
shift_ena <= 1'b1;
else if(cnt_end)
shift_ena <= 1'b0;
endmodule
3.3.5 FSM: The complete FSM(Exams/review2015 fsm)
- 此处后面三个题是一个状态机,可以直接看后面两个,希望简单一点
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;//序列检测1101的状态
parameter S4=4,S5=5,S6=6,S7=7;//S4、S5、S6、S7保持shift_ena为1!
parameter S8=8;//counting拉高,等待done_counting拉高,然后在下一状态S9拉低counting
parameter S9=9;//等待ack拉高时,传出done信号,并进入S0状态!
reg [3:0] state,next;
always@(posedge clk)
if(reset)
state <=S0;
else
state <= next;
always@(*)
case(state)
S0:next=data?S1:S0;
S1:next=data?S2:S0;
S2:next=data?S2:S3;
S3:next=data?S4:S0;
S4:next=S5;
S5:next=S6;
S6:next=S7;
S7:next=S8;
S8:next=done_counting?S9:S8;
S9:next=ack?S0:S9;
default:next=S0;
endcase
assign shift_ena=state==S4||state==S5||state==S6||state==S7;
assign counting=state==S8;
assign done=state==S9;
endmodule
3.3.6 The complete timer(Exams/review2015 fancytimer)
创建一个计时器:①当检测到特定模式(1101)时启动;②再移4位以确定延迟时间;③等待计数器完成计数,然后通知用户并等待用户确认计时器。
当接收到模式1101时,状态机必须在4个时钟周期内断言输出shift_ena。此后,状态机声明其计数输出以指示其正在等待计数器,并等待直到输入done_counting为高。
串行数据在数据输入引脚上可用。当接收到模式1101时,电路必须随后移入接下来的4位,即最高有效位在前。这4位确定定时器延迟的持续时间。将其称为delay [3:0]。
此后,状态机声明其计数输出以指示其正在计数。状态机必须精确计数(delay [3:0] + 1)* 1000个时钟周期
。例如,delay = 0表示计数1000个周期,而delay = 5表示计数6000个周期。同时输出当前剩余时间。
这应该等于1000个周期的延迟,然后等于1000个周期的delay-1,依此类推,直到1000个周期为0。当电路不计数时,count [3:0]输出无关紧要。
此时,电路必须断言完成,以通知用户计时器已超时,并等待直到输入ack为1才复位,以查找下一次出现的启动序列(1101)。电路应重置为开始搜索输入序列1101的状态。
这是预期输入和输出的示例。“ x”状态可能会使阅读有些混乱,它们表明FSM在该周期中不应关心该特定输入信号。例如,一旦读取了1101和delay [3:0],电路将不再查看数据输入,直到在完成所有其他操作后恢复搜索为止。在此示例中,电路的计数为2000个时钟周期,因为delay [3:0]值为4’b0001。最后几个周期以delay [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 );//与上一题目相比,shift_ena不需要输出!
parameter S = 0, S1 = 1, S2 = 2, S3 = 3, B0 = 4, B1 = 5, B2 = 6, B3 = 7, COUNT = 8, WAIT = 9;
reg[3:0] state, next_state;
reg[3:0] delay;
reg[13:0] cnt_delay;//根据这个保持counting为1
wire done_counting;
wire shift_ena;//与上一题目相比,shift_ena不需要输出!
//状态机第一部分
always@(posedge clk)begin
if(reset)
state <= S;
else
state <= next_state;
end
//状态机的第二部分,状态机和上一题目的一致!
always@(*)begin
case(state)
S:next_state=data?S1:S;
S1:next_state=data?S2:S;
S2:next_state=data?S2:S3;
S3:next_state=data?B0:S;
B0:next_state=B1;
B1:next_state=B2;
B2:next_state=B3;
B3:next_state=COUNT;
COUNT:next_state=done_counting?WAIT:COUNT;
WAIT:next_state=ack?S:WAIT;
endcase
end
//shift_ena和上一题目的一致,就是不需要输出
//shift_ena拉高,表示已经检测到1101
//后面就开始使用移位寄存器采取count数据,
assign shift_ena = (state == B0 || state == B1 || state == B2 || state == B3);
//使用移位寄存器采取count数据,
always@(posedge clk)begin
if(reset)
delay <= 0;
else if(shift_ena)
delay <= {delay[2:0], data};
end
//使用计数器,控制counting状态
always@(posedge clk)begin
if(reset)
cnt_delay <= 0;
else
case(state)
COUNT:cnt_delay <= cnt_delay + 1;
default:cnt_delay <= 0;
endcase
end
//好好理解此处的题意
assign done_counting = (cnt_delay == (delay + 1) * 1000 - 1);
assign count = delay - cnt_delay / 1000;
assign counting = state == COUNT;
assign done = state == WAIT;
endmodule
3.3.7 FSM: One-hot logic equations(Exams/review2015 fsmonehot)
- 连续三个题目就是这个状态机!
Derive next-state logic equations and output logic equations by inspection assuming the following one-hot encoding is used: (S, S1, S11, S110, B0, B1, B2, B3, Count, Wait) = (10’b0000000001, 10’b0000000010, 10’b0000000100, … , 10’b1000000000)
Derive state transition and output logic equations by inspection assuming a one-hot encoding. Implement only the state transition logic and output logic (the combinational logic portion) for this state machine. (The testbench will test with non-one hot inputs to make sure you’re not trying to do something more complicated).
- 作者的独热码思维很独特!
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] | ~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