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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值