Rule90

第一次见这东西有点莫名其妙,但是其实看懂了之后就是左移和右移相异或,注意这里使用的是逻辑右移,会自动补零,不能使用算数左移<<<。

module top_module(
    input clk,
    input load,
    input [511:0] data,
    output reg[511:0] q ); 
    always@(posedge clk)
    begin
        if(load)
            q <= data;
        else begin
            q <= (q<<1)^(q>>1);
        end
    end
endmodule

Rule110

Rule90可以直接根据Left和Right异或得到,而Rule110一定要三个值进行逻辑运算得到,可以画一个卡诺图并写出逻辑表达式并计算,当然不化简肯定也是可以的。

【HDLBits刷题笔记】12 More Circuits

module top_module(
    input clk,
    input load,
    input [511:0] data,
    output reg[511:0] q
); 
    always@(posedge clk)
    begin
        if(load)
            q <= data;
        else begin
            q <= (q&~(q<<1))|(~(q>>1)&(q<<1))|(~q&(q<<1));
        end
    end
endmodule

注意左移之后参与计算的是R,右移之后参与计算的是L,一开始搞反了想了很久。

Conwaylife

需要计算邻域1的个数,注意这里的边界比较复杂,每个点都有8个邻点,成一个环形结构。

方法比较笨,就是把所有情况全部考虑一遍,注意以下几点:

1、verilog运算自动按位数最多的运算数来计算,所以计算下标时使用i-8'd15而不是i-15。

2、因为我想让循环数溢出,所以取的8位i。

网上查了一下,看了别人的做法,大致有以下几类:

1、和hdlbits提示的一样使用sv语法,使用二维数组,可以大大简化逻辑。

2、将矩阵拓展为18*18,从而减少情况的考虑。

module top_module(
    input clk,
    input load,
    input [255:0] data,
    output reg[255:0] q ); 
    reg [3:0]neig_cnt;
    reg [255:0] q_next;
    always@(posedge clk)
    begin
        if(load)
            q <= data;
        else begin
            q <= q_next;
        end
    end
    reg [15:0]loop;
    reg unsigned[7:0]i;
    always@(*)
    begin
        for(loop=0;loop<256;loop=loop+1)
        begin
            i=loop;
            if(i==255)//左上角
                neig_cnt = q[i-8'd15]+q[i+8'd1]+q[i+8'd16]+q[i+8'd15]+q[i-8'd1]+q[i-8'd17]+q[i-8'd16]+q[i-8'd31];
            else if(i==240)//右上角
                neig_cnt = q[i+8'd1]+q[i+8'd17]+q[i+8'd16]+q[i+8'd31]+q[i+8'd15]+q[i-8'd1]+q[i-8'd16]+q[i-8'd15];
            else if(i==15)//左下角
                neig_cnt = q[i-8'd15]+q[i+8'd1]+q[i+8'd16]+q[i+8'd15]+q[i-8'd1]+q[i-8'd17]+q[i-8'd16]+q[i-8'd31];
            else if(i==0)//右下角
                neig_cnt = q[i+8'd1]+q[i+8'd17]+q[i+8'd16]+q[i+8'd31]+q[i+8'd15]+q[i-8'd1]+q[i-8'd16]+q[i-8'd15];
            else if(i>240)//上方
                neig_cnt = q[i+8'd1]+q[i+8'd17]+q[i+8'd16]+q[i+8'd15]+q[i-8'd1]+q[i-8'd17]+q[i-8'd16]+q[i-8'd15];
            else if(i%16==15)//左方
                neig_cnt = q[i-8'd15]+q[i+8'd1]+q[i+8'd16]+q[i+8'd15]+q[i-8'd1]+q[i-8'd17]+q[i-8'd16]+q[i-8'd31];
            else if(i%16==0)//右方
                neig_cnt = q[i+8'd1]+q[i+8'd17]+q[i+8'd16]+q[i+8'd31]+q[i+8'd15]+q[i-8'd1]+q[i-8'd16]+q[i-8'd15];
            else if(i<15)//下方
                neig_cnt = q[i+8'd1]+q[i+8'd17]+q[i+8'd16]+q[i+8'd15]+q[i-8'd1]+q[i-8'd17]+q[i-8'd16]+q[i-8'd15];
            else//中间的点
                neig_cnt = q[i+8'd1]+q[i+8'd17]+q[i+8'd16]+q[i+8'd15]+q[i-8'd1]+q[i-8'd17]+q[i-8'd16]+q[i-8'd15];
            if(neig_cnt == 0||neig_cnt == 1)
                q_next[i] = 0;
            else if(neig_cnt == 2)
                q_next[i] = q[i];
            else if(neig_cnt == 3)
                q_next[i] = 1;
            else
                q_next[i] = 0;
        end 
    end
endmodule

看到题目最后John Conway因为COVID-19并发症去世了,有些感慨,RIP。

发表回复