https://hdlbits.01xz.net/wiki/Shift Register 与 More Circuits答案

1.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 or posedge areset)//是异步置零
        begin
            if(areset)
                q <= 4‘b0;
            else if(load)
                q <= data;
            else if(ena)
                q <= q >> 1;
        end
endmodule

2.Rotate100

module top_module(
    input clk,
    input load,
    input [1:0] ena,
    input [99:0] data,
    output reg [99:0] q); 
    reg temp;
    always@(posedge clk)
        begin
            if(load)
                q <= data;
            else if(ena == 2‘b01)
                begin
                    temp = q[0];
                    q = q >>1;
                    q[99] = temp;
                end
            else if(ena == 2‘b10)
                begin
                    temp = q[99];
                	q = q << 1;
                    q[0] = temp;
                end
            else
                q <= q;
        end
endmodule

首先这是循环移位,其次此处的swap必须做阻塞赋值,否则并发则会出错。
3.shift18

module top_module(
    input clk,
    input load,
    input ena,
    input [1:0] amount,
    input [63:0] data,
    output reg [63:0] q); 
    reg temp;
    always@(posedge clk)
        begin
            if(load)
                q <= data;
            else if(ena)
                begin
                    temp = q[63];
                    case(amount)
                        2‘b00 : begin q = q << 1;end
                        2‘b01 : begin q = q << 8;end
                        2‘b10 : begin q = q >> 1; q[63:62] = {2{temp}};end
                        2‘b11 : begin q = q >> 8; q[63:56] = {8{temp}};end
                        default:;
                    endcase
                end
            else
                q <= q;
        end
endmodule

注意规则:算术左移和逻辑左移一致,右移是带符号位填充而非简单的0填充。
4.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)
                q <= 5‘h1;
            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

本题实现了一个伽罗瓦线性反馈移位寄存器,通常这类寄存器被用来生成伪随机数序列,有许多应用。我也是第一次接触,不太熟悉。
参考链接
5.3bitLFSR

  module top_module (
	input [2:0] SW,      // R
	input [1:0] KEY,     // L and clk
	output [2:0] LEDR);  // Q
    always@(posedge KEY[0])
        begin
            LEDR[0] <= (KEY[1]) ? SW[0] : LEDR[2];
            LEDR[1] <= (KEY[1]) ? SW[1] : LEDR[0];
            LEDR[2] <= (KEY[1]) ? SW[2] : (LEDR[1] ^ LEDR[2]);
        end
endmodule
module top_module(
    input clk,
    input reset,    // Active-high synchronous reset to 32‘h1
    output [31:0] q
); 
    integer i;
    always@(posedge clk)
        begin
            if(reset)
                q <= 32‘h1;
            else
                begin
                    for(i=31; i>=0; i--)
                        begin
                            if(i==31)  
                                q[i] <= q[0];
                            else if(i==21 || i==1 || i==0)
                                q[i] <= q[i+1] ^ q[0];
                            else
                                q[i] <= q[i+1];
                        end
                end
        end
endmodule

需要注意的是为伽罗瓦LFSR,而且索引是从0开始的。
7.shift register

module top_module (
    input clk,
    input resetn,   // synchronous reset
    input in,
    output out);
    reg d0;
    reg d1;
    reg d2;
    
    always@(posedge clk)
        begin
            if(~resetn)
                begin
                    d0 <= 1‘b0;
                    d1 <= 1‘b0;
                    d2 <= 1‘b0;
                    out <= 1‘b0;
                end
            else
                begin
                    d0 <= in;
                    d1 <= d0;
                    d2 <= d1;
                    out <= d2;
                end
        end
endmodule

8.shift register

module top_module (
    input [3:0] SW,
    input [3:0] KEY,
    output [3:0] LEDR
); //
    MUXDFF muxdff3(KEY[3], KEY[1], SW[3], KEY[2], KEY[0], LEDR[3]);
    MUXDFF muxdff2(LEDR[3], KEY[1], SW[2], KEY[2], KEY[0], LEDR[2]);
    MUXDFF muxdff1(LEDR[2], KEY[1], SW[1], KEY[2], KEY[0], LEDR[1]);
    MUXDFF muxdff0(LEDR[1], KEY[1], SW[0], KEY[2], KEY[0], LEDR[0]);
endmodule

module MUXDFF (
	input w,
	input e,
	input r,
	input l,
	input clk,
	output q);
    wire res;
    wire d;
    assign res = (e)? w : q;
    assign d = (l)? r : res;
    always@(posedge clk)
        q <= d;
endmodule

9.3-input LUT

module top_module (
    input clk,
    input enable,
    input S,
    input A, B, C,
    output Z ); 
    reg[7:0] r;
    always@(posedge clk)
        begin
            if(enable)
                begin
                    r = r<<1;
                    r[0] = S;
                end           
           
        end
    always@(A or B or C or r)
        begin
             case({{A},{B},{C}})
                  3‘b000 : Z <= r[0];
                  3‘b001 : Z <= r[1];
                  3‘b010 : Z <= r[2];
                  3‘b011 : Z <= r[3];
                  3‘b100 : Z <= r[4];
                  3‘b101 : Z <= r[5];
                  3‘b110 : Z <= r[6];
                  3‘b111 : Z <= r[7];
                  default:;
             endcase  
        end
endmodule

本题容易出错在于,输出是异步输出,而非同步输出。


以下是more circuits的内容,只有三个题目就不单独写了。
1.rule90

module top_module(
    input clk,
    input load,
    input [511:0] data,
    output [511:0] q ); 
    reg q_1 = 0;
    reg q_512 = 0;
    integer i;
    always@(posedge clk)
        begin
            if(load)
                q <= data;
            else 
                begin
        	   		for(i=0; i<512; i++)
                		begin
                    		if(i == 0)
                        		q[i] <= q_1 ^ q[i+1];
                    		else if(i == 511)
                        		q[i] <= q_512 ^ q[i-1];
                    		else
                        		q[i] <= q[i-1] ^ q[i+1];
                		end
                end
        end
endmodule

2.rule110

module top_module(
    input clk,
    input load,
    input [511:0] data,
    output [511:0] q
); 
    integer i;
    always@(posedge clk)
        begin
            if(load)
                q <= data;
            else
                for(i=0; i<512; i++)
                    begin
                        if(i==0)
                            q[i] <= q[i] ;
                        else if(i==511)
                            q[i] <= q[i] | q[i-1];
                        else
                            q[i] <= ~( ((~q[i]) & (~q[i-1])) | (q[i-1] & q[i] & q[i+1]) );
                    end
        end
endmodule

rule110也是很重要的东西。不过我也是第一次接触。这里要注意低位在右而不是高位。
[参考资料](https://uwe-repository.worktribe.com/output/1061875)
3.Conwaylife

module top_module(
    input clk,
    input load,
    input [255:0] data,
    output [255:0] q ); 
    
    reg[15:0] r1[15:0];
    reg[15:0] r2[15:0];
    integer i;
    integer j;
    integer k;
    integer l;
    integer count;
    always@(posedge clk)
        begin
            if(load)
                begin
                    for(i=0; i<16; i++)
                       begin
                           for(j=0; j<16; j++)
                               r1[i][j] = data[16*i + j];
                       end
                end
            else
                r1 = r2;
            
            for(i=0; i<16; i++)
                begin
                    for(j=0; j<16; j++)
                        begin
                            count = 0;
                            for(k=-1; k<2; k++)//检索相邻的活者个数
                                begin
                                  	for(l=-1; l<2; l++)
                                        begin
                                            if(r1[(i+16+k)%16][(j+16+l)%16]==1)
                                                 count++;
                                        end
                                end
                             if(r1[i][j]==1)
                                 count--;
                             if(count<2 || count>3)
                                 r2[i][j] = 1‘b0;
                             else if(count==2)
                                 r2[i][j] = r1[i][j];
                             else
                                 r2[i][j] = 1‘b1;
                        end
                 end
           for(i=0; i<16; i++)
               begin
                   for(j=0; j<16; j++)
                       q[i*16+j] = r1[i][j];
               end;
        end
endmodule

这个题的难度更大了,这里我用了两个寄存器,因为一个寄存器做综合就必须是非阻塞式的,而这里非阻塞式是没法成功的,load必须先存,然后再计算,如果是非阻塞式的,就会计算上一个周期留下的r1了而非新load进去的值,同时如果只用一个寄存器的话会比较复杂,两个寄存器看起来更清晰一些。
关于边界相邻的问题,这里其实类似卡诺图那种四面合拢的。我这里是利用类似补码的思想,取模来得到的。
最后输入输出都要作线性和矩阵之间的变换,注意不要出错。
这一题逻辑上并不那么复杂,但是实现起来会有很多问题,希望我们都能认真题会。
康威生命问题的提出者约翰康威老爷子去年因新冠肺炎去世谨在此表示哀悼


欢迎大家批评指正讨论。
[练习网址](https://hdlbits.01xz.net/wiki/Conwaylife)

https://hdlbits.01xz.net/wiki/Shift Register 与 More Circuits答案

上一篇:Web前端学习—基础篇(19)_页面布局中浮动是什么?浮动有哪些特性,它会引发什么问题?怎么清除浮动?


下一篇:SQL Server 批量导入 bulk insert