HDLbits答案更新系列9(3.2 Sequential Logic 3.2.3 Shift Registers)

目录

前言

3.2.3 Shift Registers

3.2.3.1 4-bit shift register(Shift4)

3.2.3.2 Left/right rotator(Rotate100)

3.2.3.3 Left/right arithmetic shift by 1 or 8(Shift18)

3.2.3.4 5-bit LFSR(Lfsr5)

3.2.3.5 3-bit LFSR(Mt2015 lfsr)

3.2.3.6 32-bit LFSR(Lfsr32)

3.2.3.7 Shift register(Exams/m2014 q4k)

3.2.3.8 Shift register(Exams/m2014 q4b)

3.2.3.9 3-input LUT(Exams/ece241 2013 q12)

结语

HDLbits网站链接


前言

今天更新一个小节内容,这个小节内容是以为寄存器相关的,其中涉及到CRC校验的东西,是用线性反馈移位寄存器搭建而成的,笔试面试中常有涉及,希望大家可以看一看。

3.2.3 Shift Registers

3.2.3.1 4-bit shift register(Shift4)

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, posedge areset)begin
        if(areset)begin
            q <= 4'd0;
        end
        else begin
            if(load)begin
                q <= data;
            end
            else if(ena)begin
                q <= q >> 1;
                //q <= {1'b0, q[3:1]};
            end
        end
    end

endmodule

3.2.3.2 Left/right rotator(Rotate100)

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)begin
            q <= data;
        end
        else begin
            case(ena)
                2'b00, 2'b11:begin
                    q <= q;
                end
                2'b01:begin
                    q <= {q[0], q[99:1]};
                end
                2'b10:begin
                    q <= {q[98:0], q[99]};
                end
            endcase
        end
    end

endmodule

大家注意,组合逻辑的case一定要写完整,时序逻辑的case可以不用写完整,综合出来带保持功能的触发器。博主这里没有写default,因为ena可能的四种情况均已列出,但是即使是这样,还是建议大家将default加上,养成好的习惯。

3.2.3.3 Left/right arithmetic shift by 1 or 8(Shift18)

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)begin
            q <= data;
        end
        else if(ena)begin
            case(amount)
                2'b00:begin
                    q <= {q[62:0], 1'b0};
                end
                2'b01:begin
                    q <= {q[55:0], 8'd0};
                end
                2'b10:begin
                    q <= {q[63], q[63:1]};
                end
                2'b11:begin
                    q <= { {8{q[63]}}, q[63:8] };
                end 
            endcase
        end
    end

endmodule

这道题目大家要注意,算术移位,也就是包含符号位的移位,对于正数来说,最高位为0,对于负数来说,最高位为1,所以进行算术移位时,如果是左移,那不用管符号位的问题,如果是右移,就要将符号位补在高位。

3.2.3.4 5-bit LFSR(Lfsr5)

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

endmodule

这道题目就是线性反馈移位寄存器,这种寄存器是用寄存器和异或门搭建而成的,后面会专门出一期给大家讲解。

3.2.3.5 3-bit LFSR(Mt2015 lfsr)

module top_module (
	input [2:0] SW,      // R
	input [1:0] KEY,     // L and clk
	output [2:0] LEDR);  // Q
    
    reg [2:0]	LEDR_next;
    
    always@(*)begin
    	if(KEY)begin
        	LEDR_next = SW;
        end
        else begin
        	LEDR_next[0] = LEDR[2];
    		LEDR_next[1] = LEDR[0];
    		LEDR_next[2] = LEDR[2] ^ LEDR[1];
        end
    end
    
    always@(posedge KEY[0])begin
        LEDR <= LEDR_next;
    end
    
endmodule

这道题目博主将组合逻辑和时序逻辑分开写了,可以更清楚地看到电路结构,方便设计。

3.2.3.6 32-bit LFSR(Lfsr32)

module top_module(
    input clk,
    input reset,    // Active-high synchronous reset to 32'h1
    output [31:0] q
); 
    
    reg [31:0]	q_next;

    always@(*)begin
        q_next = {q[0], q[31:1]};
        q_next[21] = q[0] ^ q[22];
        q_next[1] = q[0] ^ q[2];
        q_next[0] = q[0] ^ q[1];
    end
    
    always@(posedge clk)begin
        if(reset)begin
            q <= 32'd1;
        end
        else begin
            q <= q_next;
        end
    end

endmodule

大家根据题意设计就好了。

3.2.3.7 Shift register(Exams/m2014 q4k)

module top_module (
    input clk,
    input resetn,   // synchronous reset
    input in,
    output out);

    reg [3:0] out_reg;

    always@(posedge clk)begin
        if(resetn == 1'b0)begin
            out_reg <= 4'd0;
        end
        else begin
            out_reg <= {out_reg[2:0], in};
        end
    end
    
    assign out = out_reg[3];
    
endmodule

3.2.3.8 Shift register(Exams/m2014 q4b)

module top_module (
    input [3:0] SW,
    input [3:0] KEY,
    output [3:0] LEDR
); //

    MUXDFF u1_MUXDFF(
        .clk            (KEY[0]	),
        .w		(KEY[3]	),
        .R		(SW[3]	),
        .E		(KEY[1]	),
        .L		(KEY[2]	),
        .Q		(LEDR[3])
    );
    MUXDFF u2_MUXDFF(
        .clk	        (KEY[0]	),
        .w		(LEDR[3]),
        .R		(SW[2]	),
        .E		(KEY[1]	),
        .L		(KEY[2]	),
        .Q		(LEDR[2])
    );
    MUXDFF u3_MUXDFF(
        .clk	        (KEY[0]	),
        .w		(LEDR[2]),
        .R		(SW[1]	),
        .E		(KEY[1]	),
        .L		(KEY[2]	),
        .Q		(LEDR[1])
    );
    MUXDFF u4_MUXDFF(
        .clk	        (KEY[0]	),
        .w		(LEDR[1]),
        .R		(SW[0]	),
        .E		(KEY[1]	),
        .L		(KEY[2]	),
        .Q		(LEDR[0])
    );
    
    
endmodule

module MUXDFF (
    input clk,
    input w, R, E, L,
    output Q
);
    always@(posedge clk)begin
        if(L)begin
            Q <= R;
        end
        else begin
            if(E)begin
                Q <= w;
            end
            else begin
                Q <= Q;
            end
        end
    end

endmodule

这道题目当时把博主给搞晕了,刚开始不明白作者想干嘛,后来明白了,作者需要我们例化之前的完成的模块,大家一定要多读几遍题目好好理解一下。

3.2.3.9 3-input LUT(Exams/ece241 2013 q12)

module top_module (
    input clk,
    input enable,
    input S,
    input A, B, C,
    output Z ); 
    
    reg [7:0]	Q;
    
    always@(posedge clk)begin
        if(enable)begin
            Q <= {Q[6:0], S};
        end
    	else begin
            Q <= Q;
        end
    end
    
    assign Z = Q[{A, B, C}];

    /*
    //second way
    always@(*)begin
        case({A, B, C})
            3'b000:begin
                Z = Q[0];
            end
            3'b001:begin
                Z = Q[1];
            end
            3'b010:begin
                Z = Q[2];
            end
            3'b011:begin
                Z = Q[3];
            end
            3'b100:begin
                Z = Q[4];
            end
            3'b101:begin
                Z = Q[5];
            end
            3'b110:begin
                Z = Q[6];
            end
            3'b111:begin
                Z = Q[7];
            end
        endcase
    end
    */

endmodule

这道题目是查找表,博主的方法一比方法二简洁很多,用到了一定的技巧性,大家好好体会一下。值得一提的是,FPGA是基于查找表和寄存器的,大家一定注意到每次在quartus或者vivado中综合完成后显示的资源用量,其中就有LUT,这就是查找表逻辑。

结语

今天更新一个小节吧,对于LFSR,博主会另开一篇博客专门讲解,因为LFSR涉及到M序列的产生,这是相对重要的内容。最后如果代码中有什么有问题的地方,欢迎大家指出来,我会尽快改正~

HDLbits网站链接

https://hdlbits.01xz.net/wiki/Main_Page

你可能感兴趣的:(HDLbits答案更新系列9(3.2 Sequential Logic 3.2.3 Shift Registers))