HDLbits Conwaylife题目的一种解法

前言

最近在刷HDLBits准备今年的提前批和人秋招,目前刷到有限状态机后,发现前面的大部分题目比较基础。目前比较有难度和有意思的题目就是Conwaylife,二维元胞自动机。这里仅提供笔者自己的解法。

解题思路

比较好想到的方法就是暴力枚举所有情况,给出该情况下所有的相邻坐标。思考过后觉得暴力枚举容易出现遗漏的情况。有没有一种通用的方法可以处理所有坐标呢。

参考生命游戏的前两道题,使用另外两个向量,表示出左移的对应坐标和右移的对应坐标,直接进行异或操作进行更新。那么对于本题也可以使用另外的八个向量,一一对应q的所有相邻坐标,最后执行相加和条件语句,即可实现一个cycle完成状态更新。

为了最简化代码编写的复杂度,进行了如下思考:

1.设计变量名称时,以方向作为命名后缀(west、east、north、south)

2.首先要得到相邻位置的两个向量,对于二维矩阵的一维表现形势,不是简单的整体左右移,而是以一行为单位的左右移,得到如下坐标关系

            assign pos_e[i*16+15:i*16] = {q[(i+1)*16-2:i*16],q[i*16+15]};
            assign pos_w[i*16+15:i*16] = {q[i*16],q[i*16+15:i*16+1]};

3.然后,要得到上下位置的对应向量,这个比较简单,整体左移或右移一行的位数(16)即可:

    assign pos_n = {q[15:0],q[255:16]} ;
    assign pos_s = {q[239:0],q[255:240]};

4.对于对角线的四个位置,没有必要单独去考虑其坐标,而是将其看作是pos_n和pos_s的相邻的左右坐标即可。即直接复制1.内的表达式,将等号右侧的索引替换为pos_n和pos_s。

5.这样便得到了全部8个对应坐标的向量,将其相加后判断即可

个人解法

题目的要求为每个cycle更新一次,使用generate loop进行向量生成,使用for循环进行状态判断,得到题解如下:

module top_module(
    input clk,
    input load,
    input [255:0] data,
    output [255:0] q ); 

    wire [255:0] pos_e ;
    wire [255:0] pos_w ;
    wire [255:0] pos_n ;
    wire [255:0] pos_s ;
    wire [255:0] pos_ne ;
    wire [255:0] pos_se ;
    wire [255:0] pos_nw ;
    wire [255:0] pos_sw ;
    reg [3:0] count ;
    integer j ;
    genvar  i;
    
    assign pos_n = {q[15:0],q[255:16]} ;
    assign pos_s = {q[239:0],q[255:240]};

 	generate
        for(i = 0;i < 16; i++)begin:test
            assign pos_e[i*16+15:i*16] = {q[(i+1)*16-2:i*16],q[i*16+15]};
            assign pos_w[i*16+15:i*16] = {q[i*16],q[i*16+15:i*16+1]};
            assign pos_ne[i*16+15:i*16] = {pos_n[(i+1)*16-2:i*16],pos_n[i*16+15]};
            assign pos_nw[i*16+15:i*16] = {pos_n[i*16],pos_n[i*16+15:i*16+1]};
            assign pos_se[i*16+15:i*16] = {pos_s[(i+1)*16-2:i*16],pos_s[i*16+15]};
            assign pos_sw[i*16+15:i*16] = {pos_s[i*16],pos_s[i*16+15:i*16+1]};
 
        end
 	endgenerate
    
    always@(posedge clk)begin
        if(load)begin
            q <= data ; 
        end else begin
            for (j=0;j<=255;j++)begin
                count = pos_e[j] +pos_w[j] +pos_n[j] +pos_s[j] +pos_ne[j] +pos_se[j] +pos_nw[j] +pos_sw[j] ;
            	case(count)
                	4'd2 : q[j] <= q[j] ;
                	4'd3 : q[j] <= 1'b1 ;
                	default:q[j] <= 1'b0 ;
            	endcase
            end
        end
    end
endmodule

你可能感兴趣的:(fpga,verilog)