• HDLbits_Conwaylife


    题目介绍

    题目链接

    Conwaylife

    简介

    题目要求我们实现一个康威生命游戏的电路。

    该游戏在一个二维网格空间中进行,在该题目中是 16 * 16 的大小,每一个格子都有两种状态(0 或 1),代表死或活。

    规则:

    • 在时钟上升沿到来时,网格需要更新。
    • 若信号 load 为高电平,则更新为输入数据 data
    • 若不是,则每个网格的状态更新与它周围八个方向的网格状态有关。
      • 如果它周围八个方向的网格有 2个为活,则保持状态。
      • 如果它周围八方方向的网格有 3个为活,则该网格的状态更新为 1(活)。
      • 其他情况下,该网格状态更新为 0(死)。
    • 网格是二维的,但是存储网格是一维存储的。q[15 : 0] 是第0行, q[31 : 16] 是 第1行
    • 该二维 16 * 16的网格是无边界的,一边会延申到另一对边。

    题目分析

    解法1

    因为是延申的网络,所以我们可以将该 16 * 16的网络直接延申为 18 * 18 的网络。这样,中心 16 * 16 的网格就是我们要更新的,外面的一圈就是环形的延申出的网络。

    然后,就可以直接利用循环,避开越界的情况,直接更新了。

    解法2

    对于某个格子,暴力枚举出它每个方向的 格子情况,然后计算出它周围的存活格子数,再更新它。循环256次,将所有格子更新便可。

    那么现在,定义这 8 个方向,分别为(up, down, left, right, up_left, up_right, down_left, down_right)。

    变量简记为:

    wire [255:0] q_u;
    wire [255:0] q_l;
    wire [255:0] q_r;
    wire [255:0] q_d;
    wire [255:0] q_ul;
    wire [255:0] q_ur;
    wire [255:0] q_dl;
    wire [255:0] q_dr;

    首先来看,上下左右这四个方向如何计算。

    上下方向

    原网格定义为,output [255 : 0] q。那么对于编号为 i 的网格单元。它的上方向的网格编号显然是 i - 16

    但若 i 单元在第 0 行,那么 i - 16 会是一个负数,实际上,应该是在第 15 行。

    所以,利用Verilog的向量拼接运算即可。

    assign q_u = {q[239:0], q[255:240]};

    同理

    assign q_d = {q[15:0], q[255:16]};

    左右方向

    对于网格单元 i ,左面是 i - 1。但当该单元格在第 0列时,它的左面应该是同一行的第 15列。右面同理。

    for (i = 0; i < 16; i ++ ) begin: t1
                assign q_l[i * 16 + 15 : i * 16] = {q[i * 16 + 15 - 1 : i * 16], q[i * 16 + 15]};
                assign q_r[i * 16 + 15 : i * 16] = {q[i * 16], q[i * 16 + 15 : i * 16 + 1]};
    end
    对角线方向

    当处理对角线的情况时候,就不能与上下左右同理了。

    你会发现特殊情况(越界)有很多(一行和一列),所以这时候,直接利用之前算出的上下方向,结合左右方向的计算过程,就可以得出 对角线方向了。

    网格单元 i 的上面的左面,不就是左上嘛?

    代码实现

    代码中涉及generate for块。

    module top_module(
        input clk,
        input load,
        input [255:0] data,
        output [255:0] q ); 
        
        
        wire [255:0] q_u;
        wire [255:0] q_l;
        wire [255:0] q_r;
        wire [255:0] q_d;
        wire [255:0] q_ul;
        wire [255:0] q_ur;
        wire [255:0] q_dl;
        wire [255:0] q_dr;
        integer j;
        reg [3:0] cnt;
    
        assign q_u = {q[239:0], q[255:240]};
        assign q_d = {q[15:0], q[255:16]};
        
        genvar i;
        generate 
            for (i = 0; i < 16; i ++ ) begin: t1
                assign q_l[i * 16 + 15 : i * 16] = {q[i * 16 + 15 - 1 : i * 16], q[i * 16 + 15]};
                assign q_r[i * 16 + 15 : i * 16] = {q[i * 16], q[i * 16 + 15 : i * 16 + 1]};
                
                assign q_ul[i * 16 + 15 : i * 16] = {q_u[i * 16 + 15 - 1 : i * 16], q_u[i * 16  + 15]};
                assign q_ur[i * 16 + 15 : i * 16] = {q_u[i * 16], q_u[i * 16 + 15 : i * 16 + 1]};
                
                assign q_dl[i * 16 + 15 : i * 16] = {q_d[i * 16 + 15 - 1 : i * 16], q_d[i * 16 + 15]};
                assign q_dr[i * 16 + 15 : i * 16] = {q_d[i * 16], q_d[i * 16 + 15 : i * 16 + 1]};
            end
        endgenerate
    
        always @(posedge clk) begin
            if (load) begin
            	q <= data;
            end
            else begin
                for (j = 0; j < 256; j = j + 1) begin
                    cnt = q_u[j] + q_d[j] + q_l[j] + q_r[j] + q_ul[j] + q_ur[j] + q_dl[j] + q_dr[j];
                    case (cnt)
                        4'd2: q[j] <= q[j];
                        4'd3: q[j] <= 1;
                        default: q[j] <= 0;
                    endcase
                end
            end
        end
    endmodule

    generate for

    generate for的主要功能就是对模块或组件以及always块、assign语句进行复制。

    使用 generate for的时候,必须要注意以下几点要求

    • 在使用generate for的时候必须先声明一个 genvar变量,用作 for的循环变量。genvar是generate语句中的一种变量类型,用于在generate for语句中声明一个正整数的索引变量。
    • for里面的内嵌语句,必须写在begin-end
    • 尽量对begin-end顺序块进行命名

    generate for的语法示例如下:

    genvar i;
    generate for (i = 0; i < 4; i = i + 1) begin: gen_assign_temp
        assign temp[i] = indata[2 * i + 1 : 2 * i];
    end
    endgenerate

    __EOF__

  • 本文作者: 江水为竭
  • 本文链接: https://www.cnblogs.com/Az1r/p/17691237.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    【Linux】系统安全及应用
    【学习笔记二十七】EWM存储类型控制
    迪拜之行回顾:CESS 的 DePIN 创新之旅
    vue3+ts+tinynce富文本编辑器+htmlDocx+file-saver 配合实现word下载
    mybatis-plus报错:Invalid bound statement (not found)
    MySql学习笔记02——MySql的简单介绍
    PHP之美团餐饮系统,订单推送,订单同步,订单消息回调
    一文了解JPA、Hibernate、Spring Data JPA之间的爱恨情仇
    2023年天津农学院专升本专业课报名、确认缴费及准考证打印流程
    【pytorch笔记】第一篇 环境搭建(Windows10)
  • 原文地址:https://www.cnblogs.com/Az1r/p/17691237.html