Verilog HDLBits 第二十一期:3.3.1 Building larger circuits(3.3.1-3.3.7)

目录

前言

3.3.1 Counter with period 1000(Exams/review2015 count1k)

Solution:

3.3.2 4-bit shift register and down counter(Exams/review2015 shiftcount)

Solution:

3.3.3 FSM:Sequence 1101 recognizer(Exams/review2015 fsmseq)

Solution:

 3.3.4 FSM:Enable shift register(Exams/review2015 fsmshift)

Solution:

3.3.5 FSM:The complete FSM(Exams/review2015 fsm)

Solution:

 3.3.6 The complete timer(Exams/review2015 fancytimer)

Solution:

3.3.7 FSM:One-hot logic equations(Exams/review2015 fsmonehot)

Solution:


前言

HDLbits网站如下

Problem sets - HDLBits (01xz.net)

从本期开始我们继续HDLbits第三章Circuits的学习,本期的内容是Building larger circuits(3.3.1-3.3.7)


3.3.1 Counter with period 1000(Exams/review2015 count1k)

构建一个计数范围为0到999(含0到999)的计数器,周期为1000个周期。复位输入是同步的,应将计数器重置为0。

Solution:

module top_module (
    input clk,
    input reset,
    output [9:0] q);
    always@(posedge clk) begin
        if(reset)
            q<=10'd0;
        else if(q==10'd999)
            q<=10'd0;
        else
            q<=q+10'd1;
    end

endmodule

3.3.2 4-bit shift register and down counter(Exams/review2015 shiftcount)

这是一系列五个练习的第一部分,这些练习用几个较小的电路构建复杂的计数器。有关整体设计,请参见 3.3.6the final exercise

构建一个四位移位寄存器,它也可以作为下行(递减)计数器。当shift_ena为1时,data向最高有效位移位即左移。当count_ena为1时,移位寄存器中当前的数字递减。由于整个系统从未同时使用shift_ena和count_ena,因此如果两个控制输入都为1(这主要意味着哪种情况具有更高的优先级),则电路的功能无关紧要。

Solution:

module top_module (
    input clk,
    input shift_ena,
    input count_ena,
    input data,
    output [3:0] q);
    always@(posedge clk) begin
        if(shift_ena)
            q<={q[2:0],data};
        else if(count_ena)
            q<=q-1;  
    end
    
endmodule

3.3.3 FSM:Sequence 1101 recognizer(Exams/review2015 fsmseq)

这是一系列五个练习的第二部分,这些练习用几个较小的电路构建复杂的计数器。有关整体设计,请参见 3.3.6the final exercise

构建一个在输入比特流中搜索序列1101的有限状态机。找到序列后,应将start_shifting设置为1,直到复位。保持最终状态是为了在一个尚未实施的更大的FSM中模拟前往其他状态。我们将在接下来的几个练习中扩展此FSM。

Solution:

module top_module (
    input clk,
    input reset,      // Synchronous reset
    input data,
    output start_shifting);
    parameter s0=0,s1=1,s11=2,s110=3,s1101=4;
    reg [2:0]state,next;
    
    always@(posedge clk) begin
        if(reset)
            state<=0;
        else
            state<=next;
    end
    
    always@(*) begin
        case(state)
            s0:next=data?s1:s0;
            s1:next=data?s11:s0;
            s11:next=data?s11:s110;
            s110:next=data?s1101:s0;
            s1101:next=s1101;
        endcase
    end
    
    assign start_shifting=(state==s1101);

endmodule

 3.3.4 FSM:Enable shift register(Exams/review2015 fsmshift)

这是一系列五个练习的第三部分,这些练习用几个较小的电路构建复杂的计数器。有关整体设计,请参见 3.3.6the final exercise

作为用于控制移位寄存器的FSM的一部分,我们希望能够在检测到正确的位模式时,使移位寄存器能够精确地工作4个时钟周期。我们在3.3.3中处理序列检测,因此FSM的这部分仅处理移位寄存器的4个周期启用。

无论何时复位FSM,都要将shift_ena有效4个周期,然后永远为0(直到复位)。

Solution:

module top_module (
    input clk,
    input reset,      // Synchronous reset
    output shift_ena);
    reg [2:0]cnt;
    always@(posedge clk) begin
        if(reset)
            cnt<=0;
        else if(cnt<=3)
            cnt<=cnt+1;
        else
            cnt<=cnt;
    end
    
    always@(*) begin
        if(cnt==4)
            shift_ena=0;
     	else
            shift_ena=1;
    end
            
endmodule

3.3.5 FSM:The complete FSM(Exams/review2015 fsm)

这是一系列五个练习的第四部分,这些练习用几个较小的电路构建复杂的计数器。有关整体设计,请参见 3.3.6the final exercise

我们想创建一个计时器:

  1. 当检测到特定序列(1101)时启动
  2. 再移位四位以确定延迟的持续时间
  3. 等待计数器完成计数
  4. 通知用户并等待用户确认计时器。

在这个问题中,只实现控制计时器的FSM。这里不包括数据路径(计数器和一些比较器)。

串行数据在数据输入引脚上可用。当接收到序列1101时,状态机必须在整整4个时钟周期内使shift_ena有效。

之后,状态机使其计数输出有效,以指示它正在等待计数器,并等待直到输入done_counting为高。

此时,状态机必须断言done以通知用户计时器已超时,并等待直到输入 ack为1,然后再复位,以查找启动序列的下一次出现(1101)。

状态机应复位为开始搜索输入序列1101的状态。

以下是预期输入和输出的示例。“x”状态读起来可能有点混乱。它们表明FSM不应该关心该周期中的特定输入信号。例如,一旦检测到1101模式,FSM将不再查看数据输入,直到完成所有其他操作后恢复搜索。

Hint:

Solution:

module top_module (
    input clk,
    input reset,      // Synchronous reset
    input data,
    output shift_ena,
    output counting,
    input done_counting,
    output done,
    input ack );
    parameter s=0,s1=1,s11=2,s110=3,shift=5,count=6,idle=7;
    reg [2:0]state,next;
    reg [2:0]cnt;
    
    always@(*) begin
        case(state)
            s:next=data?s1:s;
            s1:next=data?s11:s;
            s11:next=data?s11:s110;
            s110:next=data?shift:s;
            shift:next=(cnt<3)?shift:count;
            count:next=done_counting?idle:count;
            idle:next=ack?s:idle;
        endcase
    end
    
    always@(posedge clk) begin
        if(reset)
            state<=s;
        else
            state<=next;
    end
    
    always@(posedge clk) begin
        case(state)
            s110:cnt<=0;
            shift:cnt<=cnt+1;
        endcase
    end
    
    assign shift_ena = (state==shift);                
    assign counting = (state==count);
    assign done = (state==idle);
                                                   
endmodule

 3.3.6 The complete timer(Exams/review2015 fancytimer)

这是一系列五个练习的第五部分,这些练习用几个较小的电路构建复杂的计数器。

我们想创建一个计时器:

  1. 当检测到特定序列(1101)时启动
  2. 再移位四位以确定延迟的持续时间
  3. 等待计数器完成计数
  4. 通知用户并等待用户确认计时器。

串行数据在data输入引脚上可用。当接收到序列1101时,电路必须在接下来的4位中移位,最高有效位首先移位。这4位决定计时器延迟的持续时间。我称之为delay[3:0]。

之后,状态机使其counting输出有效,以指示其正在计数。状态机必须精确计数(delay[3:0]+1)*1000个时钟周期。 例如,delay=0表示计数1000个周期,delay=5表示计数6000个周期。同时输出当前剩余时间。这等价于delay对应1000个周期,delay-1对应1000个周期,依此类推,直到0对应1000个周期。当电路不计数时,count[3:0]输出是dont-care(无论什么值便于实现)。

此时,电路必须断言done,以通知用户计时器已超时,并等待输入ack为1,然后再复位,以查找下一次出现的启动序列(1101)。

电路应复位至开始搜索输入序列1101的状态。

以下是预期输入和输出的示例。“x”状态读起来可能有点混乱。它们表明FSM不应该关心该周期中的特定输入信号。例如,一旦1101和delay[3:0]被读取,电路将不再查看数据输入,直到完成所有其他操作后恢复搜索。在本例中,电路计数2000个时钟周期,因为delay[3:0]值为4'b0001。最后几个周期开始另一次计数,delay[3:0]=4'b1110,这将计15000个周期。

Solution:

module top_module (
    input clk,
    input reset,      // Synchronous reset
    input data,
    output [3:0] count,
    output counting,
    output done,
    input ack );
    parameter idle=0,s1=1,s11=2,s110=3,shift=4,timer=5,wait_=6;
    
    reg[2:0]state,next;
        
    always@(*) begin
        case(state)
            idle:next=data?s1:idle;
            s1:next=data?s11:idle;
            s11:next=data?s11:s110;
            s110:next=data?shift:idle;
            shift:next=(shift_cnt==3)?timer:shift;
            timer:next=(timer_cnt==(delay+1)*1000-1)?wait_:timer;
            wait_:next=ack?idle:wait_;
        endcase
    end
            
    always@(posedge clk) begin
        if(reset)
            state<=idle;
        else
            state<=next;
    end
    
    reg[3:0]delay;
    always@(posedge clk) begin
        if(reset)
            delay<=4'b0;
        else if(state==shift)
            delay<={delay[2:0],data};
        else
            delay<=delay;
    end
    
    reg[1:0]shift_cnt;
    always@(posedge clk) begin
        if(reset)
            shift_cnt<=0;
        else if(state==shift&&shift_cnt<2'd3)
            shift_cnt<=shift_cnt+2'd1;
        else
            shift_cnt<=0;
    end
        
    reg[15:0]timer_cnt;    
    always@(posedge clk) begin
        if(reset)
            timer_cnt<=16'd0;
        else if(state==timer&&timer_cnt<((delay+1)*1000-1))
            timer_cnt<=timer_cnt+16'd1;
        else
            timer_cnt<=16'd0;
    end
    
    reg[10:0]cnt_1k;
    reg[3:0]num_1k;

    always@(posedge clk) begin
        if(reset)
            cnt_1k<=11'd0;
        else if(state==timer&&cnt_1k!=11'd999)
            cnt_1k<=cnt_1k+11'd1;
        else
            cnt_1k<=11'd0;
    end
    
    always@(posedge clk) begin
        if(reset)
            num_1k<=4'd0;
        else if(cnt_1k==11'd999)
            num_1k<=num_1k+1'b1;
        else if(state==timer)
            num_1k<=num_1k;
        else
            num_1k<=4'd0;
    end
    
    assign counting=(state==timer);
    assign done=(state==wait_);
    assign count=(state==timer)?(delay-num_1k):4'b0;
                               
endmodule

3.3.7 FSM:One-hot logic equations(Exams/review2015 fsmonehot)

给定以下具有3个输入、3个输出和10个状态的状态机:

假设使用以下独热码,通过检查推导next_state态逻辑方程和output逻辑方程:(S、S1、S11、S110、B0、B1、B2、B3、Count、Wait)=(10'b0000000001、10'b0000000010、10'b0000000100、…、10'b1000000000) 

编写生成以下方程式的代码:

  • B3_next -- B3的下个状态
  • S_next
  • S1_next
  • Count_next
  • Wait_next
  • done -- output logic
  • counting
  • shift_ena

Solution:

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;
    reg[9:0]next;
    
    always@(*) begin
        next[S]=(state[S]&&~d)||(state[S1]&&~d)||(state[S110]&&~d)||(state[Wait]&&ack);
        next[S1]=state[S]&&d;
        next[S11]=state[S1]&&d;
        next[S110]=state[S11]&&~d;
        next[B0]=state[S110]&&d;
        next[B1]=state[B0];
        next[B2]=state[B1];
        next[B3]=state[B2];
        next[Count]=state[B3]||state[Count]&&~(done_counting);
        next[Wait]=state[Count]&&done_counting||state[Wait]&&~ack;
    end
    
    assign B3_next=next[B3];
    assign S_next=next[S];
    assign S1_next=next[S1];
    assign Count_next=next[Count];
    assign Wait_next=next[Wait];
    
    assign done=state[Wait];
    assign counting=state[Count];
    assign shift_ena=state[B0]||state[B1]||state[B2]||state[B3];
        
endmodule

3.3.6分解成小任务就没有那么难了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值