verilog练习:hdlbits网站上的做题笔记(7)!强烈推荐!

本文详细介绍了使用Verilog进行数字逻辑设计的几个实例,包括计数器、移位寄存器、有限状态机(FSM)的设计。通过hdlbits网站的练习题目,展示了如何实现周期为1000的计数器、4位移位寄存器和下降计数器,以及不同实现方式的FSM,如序列检测器、计数器触发的移位寄存器和完整计时器。每个案例都详细阐述了状态转移逻辑和输出逻辑,有助于读者深入理解Verilog编程和数字逻辑设计。
摘要由CSDN通过智能技术生成

前言

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

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰之行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值