Verilog学习-03

考研上微电子入了材料坑,开始自学verilog

此文很多也是在其他优秀的博文中复制过来

(在此也非常感谢大家在网上分享的笔记)

仅为方便记录自己学习的笔记

习题链接:HDLBits

本文大部分参考链接:https://www.cnblogs.com/LhTian/p/16608404.html


三,电路

3.2,时序逻辑电路

计数器

四位二进制计数器

构建一个4位二进制计数器,计数从0到15(包括15),周期为16。复位输入是同步的,应该将计数器复位为0。

module top_module (
    input clk,
    input reset,      // Synchronous active-high reset
    output [3:0] q);
    
    always@(posedge	clk)begin
        if(reset==1)
            q	<=	0;
        else	begin
            if(q==15)
                q	<=	0;
            else
            	q	<=	q+1;
        end
    end

endmodule
慢速十进制计数器

构建一个从0到9(包括9)的十进制计数器,周期为10。复位输入是同步的,应该将计数器复位为0。我们希望能够暂停计数器,而不是总是在每个时钟周期增加,因此slowena输入指示计数器何时应该增加。

module top_module (
    input clk,
    input slowena,
    input reset,
    output [3:0] q);
    
    always@(posedge	clk)begin
        if(reset==1)
            q	<=	0;
        else	begin
            if(slowena==1)begin
            	if(q==9)
               		q	<=	0;
            	else
            		q	<=	q+1;
            end
            else
                q	<=	q;
        end
    end
    
endmodule
1-12计数器

Design a 1-12 counter with the following inputs and outputs:

  • Reset Synchronous active-high reset that forces the counter to 1
  • Enable Set high for the counter to run
  • Clk Positive edge-triggered clock input
  • Q[3:0] The output of the counter
  • c_enable, c_load, c_d[3:0] Control signals going to the provided 4-bit counter, so correct operation can be verified.

You have the following components available:

  • the 4-bit binary counter (count4) below, which has Enable and synchronous parallel-load inputs (load has higher priority than enable). The count4 module is provided to you. Instantiate it in your circuit.
  • logic gates
The c_enablec_load, and c_d outputs are the signals that go to the internal counter's enableload, and d inputs, respectively. Their purpose is to allow these signals to be checked for correctness.
module top_module (
    input clk,
    input reset,
    input enable,
    output [3:0] Q,
    output c_enable,
    output c_load,
    output [3:0] c_d
); //

    count4 the_counter (clk, c_enable, c_load, c_d, Q );
    assign c_enable = enable;  //直接将输入的使能信号给到c_enable即可
    //组合逻辑,同步复位
    always @(*) begin
        if(reset == 1'b1) begin
            c_load = 1'b1;    //这里的初值题目似乎没有明确说,提交后根据时序图进行修改  
            c_d    = 3'd1;
        end
        else begin
            if( Q==4'd12 && enable == 1'b1) begin //计数到12并且enable为高时,回到初值
                c_load = 1'b1;
                c_d    = 3'd1;
            end
            else begin
                c_load = 1'b0;
                c_d    = 3'd0;
            end
        end
    end

endmodule
模1000

From a 1000 Hz clock, derive a 1 Hz signal, called OneHertz, that could be used to drive an Enable signal for a set of hour/minute/second counters to create a digital wall clock. Since we want the clock to count once per second, the OneHertz signal must be asserted for exactly one cycle each second. Build the frequency divider using modulo-10 (BCD) counters and as few other gates as possible. Also output the enable signals from each of the BCD counters you use (c_enable[0] for the fastest counter, c_enable[2] for the slowest).

The following BCD counter is provided for you. Enable must be high for the counter to run. Reset is synchronous and set high to force the counter to zero. All counters in your circuit must directly use the same 1000 Hz signal.

module bcdcount (
	input clk,
	input reset,
	input enable,
	output reg [3:0] Q
);
module top_module (
    input clk,
    input reset,
    output OneHertz,
    output [2:0] c_enable
); //
    wire	[3:0]q0,q1,q2;
    bcdcount counter0(clk,reset,c_enable[0],q0);//个位
    bcdcount counter1(clk,reset,c_enable[1],q1);//十位
    bcdcount counter2(clk,reset,c_enable[2],q2);//百位
    
    always@(*)begin
        if(reset==1)begin
            OneHertz	=	0;
            c_enable <= 3'b001;
        end
        else	begin
        	if(q0==9)begin
            	c_enable <= 3'b011;
            	if(q1==9)begin
                	c_enable <= 3'b111;
        			if(q2==9)begin
            			if(OneHertz==0)
            				OneHertz	=	1;
            			else
                			OneHertz	=	0;
                	end
                end
            end
            else
        		c_enable <= 3'b001;   
        end
    end
   
endmodule
四位十进制计数器

Build a 4-digit BCD (binary-coded decimal) counter. Each decimal digit is encoded using 4 bits: q[3:0] is the ones digit, q[7:4] is the tens digit, etc. For digits [3:1], also output an enable signal indicating when each of the upper three digits should be incremented.

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    output [3:1] ena,
    output [15:0] q);
    
    always@(posedge clk) begin
        if (reset == 1'b1)
            q[3:0] <= 4'd0;
        else if(q[3:0] == 4'd9)
            q[3:0] <= 4'd0;
        else
            q[3:0] <= q[3:0] + 1; 
    end
    
    assign ena[1] = (q[3:0] == 4'd9) ? 1 : 0; 
    assign ena[2] = (q[7:4] == 4'd9 && q[3:0] == 4'd9) ? 1:0;
    assign ena[3] = (q[11:8] == 4'd9 && q[7:4] == 4'd9 && q[3:0] == 4'd9) ? 1 : 0;
    
    counter10bcd counter10bcd_inst2(clk,ena[1],reset,q[7:4]);
    counter10bcd counter10bcd_inst3(clk,ena[2],reset,q[11:8]);
    counter10bcd counter10bcd_inst4(clk,ena[3],reset,q[15:12]);
        
endmodule

module counter10bcd (
    input clk,
    input ena,
    input reset,
    output [3:0] q);
    
    always@(posedge clk) begin
        if (reset == 1'b1)
            q <= 4'd0;
        else if(ena == 1'b1) begin
            if (q == 4'd9)
                q <= 4'd0;
            else
                q <= q + 1'b1;
        end
        else
            q <= q;      
    end
endmodule
十二小时时钟

Create a set of counters suitable for use as a 12-hour clock (with am/pm indicator). Your counters are clocked by a fast-running clk, with a pulse on ena whenever your clock should increment (i.e., once per second).

reset resets the clock to 12:00 AM. pm is 0 for AM and 1 for PM. hh, mm, and ss are two BCD (Binary-Coded Decimal) digits each for hours (01-12), minutes (00-59), and seconds (00-59). Reset has higher priority than enable, and can occur even when not enabled.

The following timing diagram shows the rollover behaviour from 11:59:59 AM to 12:00:00 PM and the synchronous reset and enable behaviour.

module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss); //开始写时把这一个;忘了,导致一直报错
    
    wire	[5:1]e;
    
    always @(posedge clk) begin
        if(reset==1)begin
            pm	<=	0;
            hh	<=	8'b00010010;
        end
        else	begin
            if(e[4]==1 && ena==1)begin
                if(hh[3:0]==9)
                    hh	<=	8'b00010000;
                else
                    hh[3:0]	<=	hh[3:0]+1;
            end
            if(hh==8'b00010010	&&	mm==8'b01011001 &&ss==8'b01011001)    //刚开始写的时候只写了时针和分针,忽略了秒针,导致仿真一直不对
              	hh	<=	8'b00000001;    //12:59:59时变为01:00:00
            if(hh==8'b00010001	&&	mm==8'b01011001 &&ss==8'b01011001)
             	pm	<=	~pm;    //11:59:59am变为12:00:00pm
        end              
   	end
    
    assign e[1] = (ss[3:0]==9 && ena==1) ? 1:0;     //秒针个位进位信号
    //需要加上ena==1条件,不然当ena在ss[3:0]==9时正好变为0,此时ss[3:0]不变,但是ss[7:4]会一直增加,其他同理
    assign e[2] = (ss==8'b01011001 && ena==1) ? 1:0;    //秒针十位进位信号
    assign e[3] = (mm[3:0]==9&&ss==8'b01011001 && ena==1) ? 1:0;  //分针个位进位信号
    assign e[4] = (mm==8'b01011001&&ss==8'b01011001 && ena==1) ? 1:0; //分针十位进位信号
    
    bcd10	eg0(clk,reset,ena,ss[3:0]);    //秒针个位
    bcd6	eg1(clk,reset,e[1],ss[7:4]);    //秒针十位
    bcd10	eg2(clk,reset,e[2],mm[3:0]);    //分针个位 
    bcd6	eg3(clk,reset,e[3],mm[7:4]);    //分针十位

endmodule

module	bcd10(
	input	clk,
	input	reset,
	input	ena,
    output	[3:0]q);    //bcd模十计数器
    
    always @(posedge clk) begin
        if(reset==1)
            q	<=	0;
        else	begin
            if(ena==1)begin
                if(q==9)
                    q	<=	0;
                else
                    q	<=	q+1;
            end
            else
                q	<=	q;
        end
    end
                  
endmodule

module	bcd6(
	input	clk,
	input	reset,
	input	ena,
    output	[3:0]q);    //bcd模六计数器
    
    always @(posedge clk) begin
        if(reset==1)
            q	<=	0;
        else	begin
            if(ena==1)begin
                if(q==5)
                    q	<=	0;
                else
                    q	<=	q+1;
            end
            else
                q	<=	q;
        end
    end
                  
endmodule

(23.11.22)

移位寄存器

四位移位寄存器

Build a 4-bit shift register (right shift), with asynchronous reset, synchronous load, and enable.

  • areset: Resets shift register to zero.置零
  • load: Loads shift register with data[3:0] instead of shifting.置数
  • ena: Shift right (q[3] becomes zero, q[0] is shifted out and disappears).移位
  • q: The contents of the shift register.输出

If both the load and ena inputs are asserted (1), the load input has higher priority.

load的优先级比ena高

module top_module(
    input clk,
    input areset,  // async active-high reset to zero
    input load,
    input ena,
    input [3:0] data,
    output reg [3:0] q); 
    
    always@(posedge	clk	or	posedge	areset)begin    //areset异步复位
        if(areset==1)
            q	<=	0;
        else	begin
            if(load==1)    //把ena条件放在load中,可以使load优先级高于ena
                q	<=	data;
            else	begin
                if(ena==1)
                    q	<=	{1'b0,q[3:1]};
                else
                    q	<=	q;
            end
        end
    end

endmodule
左右移位旋转器

Build a 100-bit left/right rotator, with synchronous load and left/right enable. A rotator shifts-in the shifted-out bit from the other end of the register, unlike a shifter that discards the shifted-out bit and shifts in a zero. If enabled, a rotator rotates the bits around and does not modify/discard them.

构建一个100位左右旋转器,具有同步加载和左右启用。旋转器从寄存器的另一端移入移出位,不像移位器丢弃移出位并移进一个零。如果启用,旋转器会旋转这些位,不会修改或丢弃它们。

  • load: Loads shift register with data[99:0] instead of rotating.
  • ena[1:0]: Chooses whether and which direction to rotate.
    • 2'b01 rotates right by one bit
    • 2'b10 rotates left by one bit
    • 2'b00 and 2'b11 do not rotate.
  • q: The contents of the rotator.
module top_module(
    input clk,
    input load,
    input [1:0] ena,
    input [99:0] data,
    output reg [99:0] q); 
    
    always@(posedge	clk)begin
        if(load==1)
            q	<=	data;
        else	begin
            case(ena)
                2'b01:q	<=	{q[0],q[99:1]};
                2'b10:q	<=	{q[98:0],q[99]};
            	default:q	<=	q;
            endcase
        end
    end

endmodule
左/右移1或8位寄存器

Build a 64-bit arithmetic shift register, with synchronous load. The shifter can shift both left and right, and by 1 or 8 bit positions, selected by amount.

An arithmetic right shift shifts in the sign bit of the number in the shift register (q[63] in this case) instead of zero as done by a logical right shift. Another way of thinking about an arithmetic right shift is that it assumes the number being shifted is signed and preserves the sign, so that arithmetic right shift divides a signed number by a power of two.

There is no difference between logical and arithmetic left shifts.

建立一个算术移位寄存器,左移无需考虑是否为有符号还是无符号数,都是进行补零处理。关键是右移,如果考虑有符号数的移位,则有所不同。如果符号位为1,则右移后是补1;如果符号位为0,则右移后是补0

  • load: Loads shift register with data[63:0] instead of shifting.
  • ena: Chooses whether to shift.
  • amount: Chooses which direction and how much to shift.
    • 2'b00: shift left by 1 bit.
    • 2'b01: shift left by 8 bits.
    • 2'b10: shift right by 1 bit.
    • 2'b11: shift right by 8 bits.
  • q: The contents of the shifter.
module top_module(
    input clk,
    input load,
    input ena,
    input [1:0] amount,
    input [63:0] data,
    output reg [63:0] q); 
    
    always@(posedge	clk)begin
        if(load==1)
            q	<=	data;
        else	begin
            if(ena==1)begin
                case(amount)
                    2'b00:q	<=	{q[62:0],1'b0};
                    2'b01:q	<=	{q[55:0],8'b00000000};
                    2'b10:q	<=	{q[63],q[63:1]};
                    2'b11:q	<=	{{8{q[63]}},q[63:8]};
            	endcase
            end
            else
                q	<=	q;
        end
    end

endmodule
5位线性反馈移位寄存器

linear feedback shift register is a shift register usually with a few XOR gates to produce the next state of the shift register. A Galois LFSR is one particular arrangement where bit positions with a "tap" are XORed with the output bit to produce its next value, while bit positions without a tap shift. If the taps positions are carefully chosen, the LFSR can be made to be "maximum-length". A maximum-length LFSR of n bits cycles through 2n-1 states before repeating (the all-zero state is never reached).

The following diagram shows a 5-bit maximal-length Galois LFSR with taps at bit positions 5 and 3. (Tap positions are usually numbered starting from 1). Note that I drew the XOR gate at position 5 for consistency, but one of the XOR gate inputs is 0.

module top_module(
    input clk,
    input reset,    // Active-high synchronous reset to 5'h1
    output [4:0] q
); 
    always@(posedge	clk)begin
        if(reset==1)
            q	<=	5'h1;
        else
            q	<=	{q[0]^0,q[4],q[3]^q[0],q[2],q[1]};
    end

endmodule
移位寄存器

Write a top-level Verilog module (named top_module) for the shift register, assuming that n = 4. Instantiate four copies of your MUXDFF subcircuit in your top-level module. Assume that you are going to implement the circuit on the DE2 board.

  • Connect the R inputs to the SW switches,
  • clk to KEY[0],
  • E to KEY[1],
  • L to KEY[2], and
  • w to KEY[3].
  • Connect the outputs to the red lights LEDR[3:0].

module top_module (
    input [3:0] SW,
    input [3:0] KEY,
    output [3:0] LEDR
); //
    
    MUXDFF	eg3(KEY[0],KEY[1],KEY[2],KEY[3],SW[3],LEDR[3]);
    MUXDFF	eg2(KEY[0],KEY[1],KEY[2],LEDR[3],SW[2],LEDR[2]);
    MUXDFF	eg1(KEY[0],KEY[1],KEY[2],LEDR[2],SW[1],LEDR[1]);
    MUXDFF	eg0(KEY[0],KEY[1],KEY[2],LEDR[1],SW[0],LEDR[0]);
    
endmodule

module MUXDFF (
	input	clk,
	input	e,
	input	l,
	input	w,
	input	r,
	output	q);
    
    always@(posedge	clk)begin
        if(l==1)
            q	<=	r;
        else	begin
            if(e==1)
                q	<=	w;
            else
                q	<=	q;
        end
    end

endmodule

(23.11.23)

其他电路

康威的生命游戏

Conway's Game of Life is a two-dimensional cellular automaton.

The "game" is played on a two-dimensional grid of cells, where each cell is either 1 (alive) or 0 (dead). At each time step, each cell changes state depending on how many neighbours it has:

  • 0-1 neighbour: Cell becomes 0.
  • 2 neighbours: Cell state does not change.
  • 3 neighbours: Cell becomes 1.
  • 4+ neighbours: Cell becomes 0.

1表示细胞存活,0表示细胞死亡如果只有0或1个那么当前格子中的细胞死亡;如果是有2个细胞,则维持当前的状态;如果是有3个细胞,则当前格子中细胞存活;当出现4个以上的细胞,则当前格子中的细胞死亡。

The game is formulated for an infinite grid. In this circuit, we will use a 16x16 grid. To make things more interesting, we will use a 16x16 toroid, where the sides wrap around to the other side of the grid. For example, the corner cell (0,0) has 8 neighbours: (15,1), (15,0), (15,15), (0,1), (0,15), (1,1), (1,0), and (1,15). The 16x16 grid is represented by a length 256 vector, where each row of 16 cells is represented by a sub-vector: q[15:0] is row 0, q[31:16] is row 1, etc. (This tool accepts SystemVerilog, so you may use 2D vectors if you wish.)

  • load: Loads data into q at the next clock edge, for loading initial state.
  • q: The 16x16 current state of the game, updated every clock cycle.

The game state should advance by one timestep every clock cycle.

module top_module(
    input clk,
    input load,
    input [255:0] data,
    output [255:0] q ); 
    
    reg	[2:0]n;
    
    always@(posedge	clk)begin
        if(load==1)
            q	<=	data;
        else	begin
            for(int	i=0;i<$bits(q);i=i+1)begin
                if(i==0)
                    n	=	q[255]+q[240]+q[241]+q[15]+q[1]+q[31]+q[16]+q[17];//左上角
                    //按照此点的左上、上、右上、左、右、左下、下、右下八个区域,下同
                else	if(i==15)
                    n	=	q[254]+q[255]+q[240]+q[14]+q[0]+q[30]+q[31]+q[16];//右上角
                else	if(i==240)
                    n	=	q[239]+q[224]+q[225]+q[255]+q[241]+q[15]+q[0]+q[1];//左下角
                else	if(i==255)
                    n	=	q[238]+q[239]+q[224]+q[254]+q[240]+q[14]+q[15]+q[0];//右下角
                else	if(i>0&i<15)
                    n	=	q[i+239]+q[i+240]+q[i+241]+q[i-1]+q[i+1]+q[i+15]+q[i+16]+q[i+17];//上边界
                else	if(i>240&i<255)
                    n	=	q[i-17]+q[i-16]+q[i-15]+q[i-1]+q[i+1]+q[i-241]+q[i-240]+q[i-239];//下边界
                else	if(i%16==0)
                    n	=	q[i-1]+q[i-16]+q[i-15]+q[i+15]+q[i+1]+q[i+31]+q[i+16]+q[i+17];//左边界
                else	if(i%16==15)
                    n	=	q[i-17]+q[i-16]+q[i-31]+q[i-1]+q[i-15]+q[i+15]+q[i+16]+q[i+1];//右边界
                else
                    n	=	q[i-17]+q[i-16]+q[i-15]+q[i-1]+q[i+1]+q[i+15]+q[i+16]+q[i+17];//其他内部区域
                
                case(n)
                    3'b000:q[i]	<=	1'b0;
                    3'b001:q[i]	<=	1'b0;
                    3'b010:q[i]	<=	q[i];
                    3'b011:q[i]	<=	1'b1;
                    default:q[i]<=	1'b0;
                endcase
            end
        end
    end

endmodule

(23.11.23)

  • 32
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值