北邮数电实验模块电路:随机骰子点阵显示

双骰子点阵显示

本篇博客依旧是代码经过时序仿真验证,个人感觉没什么问题,可能点阵显示会出现问题,但微调即可。大段文本均由GPT生成。
目前这一版代码为上板子后正确代码!且更新引脚图


项目概述

  • 功能描述
    通过随机数生成器产生两个骰子的随机点数,并通过点阵 LED 显示这两个骰子的点数。点阵显示包含红色和绿色两种颜色。

  • 主要模块

    • dice:顶层模块,用于实例化和连接各子模块。
    • randomrandom2:随机数生成模块。
    • dot_matrix:点阵 LED 驱动模块。
    • test:用于定时触发骰子更新的测试模块。

模块设计与实现

顶层模块 dice

module dice(row, r_col, g_col, rst, clk, start1, start2, clk_div, dice1, dice2);
    input rst;
    input clk;
    input start1, start2;
    output [7:0] row;        // 行控制信号
    output [7:0] r_col;      // 红色列控制信号
    output [7:0] g_col;      // 绿色列控制信号
    output clk_div;
    output [3:0] dice1, dice2;

    // 实例化 test 模块
    test u_test(
        .clk(clk),
        .rst(rst),
        .dice1(dice1),
        .dice2(dice2),
        .clk_div(clk_div)
    );

    // 实例化 dot_matrix 模块
    dot_matrix u_dot_matrix (
        .clk(clk),
        .rst(rst),
        .dice1(dice1),
        .dice2(dice2),
        .row(row),
        .r_col(r_col),
        .g_col(g_col)
    );
endmodule

随机数生成模块

模块 random

该模块基于 4 位 LFSR(线性反馈移位寄存器)生成随机数,并将结果映射到骰子点数范围(1-9)。

需要注意,这里九个数值产生概率应该不相同,如果想要概率相同的话可能需要拓展线性寄存器位数,使之达到9的公倍数,再进行映射。

module random(
    input clk,
    input wire rst,
    input wire roll,
    output reg [3:0] dice
);

    reg [3:0] lfsr;

    initial begin
        lfsr <= 4'b1001;  // 初始化 LFSR,不为 0
        dice <= 4'b0000;
    end

    always @(posedge roll or posedge rst) begin
        if (rst) begin
            lfsr <= 4'b1001;
            dice <= 4'b0000;
        end else if (roll) begin
            lfsr <= {lfsr[2:0], lfsr[3] ^ lfsr[2]};
            dice <= (lfsr % 9) + 1;
        end
    end
endmodule


module random2(
    input clk,
    input wire rst,
    input wire roll,
    output reg [3:0] dice
);

    reg [3:0] lfsr;

    initial begin
        lfsr <= 4'b0001;
        dice <= 4'b0000;
    end

    always @(posedge roll or posedge rst) begin
        if (rst) begin
            lfsr <= 4'b0001;
            dice <= 4'b0000;
        end else if (roll) begin
            lfsr <= {lfsr[2:0], lfsr[3] ^ lfsr[2]};
            dice <= (lfsr % 9) + 1;
        end
    end
endmodule

点阵 LED 驱动模块

dot_matrix 模块将骰子点数转换为点阵显示的模式,并通过行列扫描驱动点阵。

module dot_matrix (
    input wire clk,           // 时钟信号
    input wire rst,           // 复位信号
    input wire [3:0] dice1,    // 输入骰子数字(1-9)
	 input wire [3:0] dice2,       //第二个骰子
    output reg [7:0] row,     // 行信号(ROW7 - ROW0)
    output reg [7:0] r_col,    // 红色列信号(R_COL7 - R_COL0)
	 output reg [7:0] g_col     // 绿色列信号
);


    reg [7:0] row_patterns;  // 行信号
    reg [2:0] red_patterns[2:0];  // 红色列信号
	 reg [2:0] green_patterns[2:0];  //绿色信号 
    reg [2:0] scan_index;         // 当前扫描行索引(0~7)
	 reg [1:0] sel;   //这是来选择列信号的,每一个时钟周期变化一次

	initial //参数初始化
	begin
		r_col <= 8'b0000_0000;
		g_col <= 8'b0000_0000;
	end
	 
always@(*)begin   //给红色信号的低三位赋值
	 case(dice1)
	 4'b0001:begin  //1
		red_patterns[0] = 3'b000;
		red_patterns[1] = 3'b010;
		red_patterns[2] = 3'b000;
		end
	 4'b0010:begin  //2
		red_patterns[0] = 3'b001;
		red_patterns[1] = 3'b000;
		red_patterns[2] = 3'b100;
		end
	 4'b0011:begin  //3
		red_patterns[0] = 3'b100;
		red_patterns[1] = 3'b010;
		red_patterns[2] = 3'b001;
		end
	 4'b0100:begin  //4
		red_patterns[0] = 3'b101;
		red_patterns[1] = 3'b000;
		red_patterns[2] = 3'b101;
		end
	 4'b0101:begin  //5
		red_patterns[0] = 3'b101;
		red_patterns[1] = 3'b010;
		red_patterns[2] = 3'b101;
		end
	 4'b0110:begin  //6
		red_patterns[0] = 3'b111;
		red_patterns[1] = 3'b000;
		red_patterns[2] = 3'b111;
	   end
	 4'b0111:begin   //7
		red_patterns[0] = 3'b111;
		red_patterns[1] = 3'b010;
		red_patterns[2] = 3'b111;
		end
	 4'b1000:begin    //8
		red_patterns[0] = 3'b111;
		red_patterns[1] = 3'b101;
		red_patterns[2] = 3'b111;
		end
	 4'b1001:begin    //9
		red_patterns[0] = 3'b111;
		red_patterns[1] = 3'b111;
		red_patterns[2] = 3'b111;
		end
		default:begin  //默认都不亮
		red_patterns[0] = 3'b000;
		red_patterns[1] = 3'b000;
		red_patterns[2] = 3'b000;
		end
	 endcase
	 
	 case(dice2)   //给绿色信号的高三位赋值
	 4'b0001:begin  //1
		green_patterns[0] = 3'b000;
		green_patterns[1] = 3'b010;
		green_patterns[2] = 3'b000;
		end
	 4'b0010:begin  //2
		green_patterns[0] = 3'b001;
		green_patterns[1] = 3'b000;
		green_patterns[2] = 3'b100;
		end
	 4'b0011:begin  //3
		green_patterns[0] = 3'b100;
		green_patterns[1] = 3'b010;
		green_patterns[2] = 3'b001;
		end
	 4'b0100:begin  //4
		green_patterns[0] = 3'b101;
		green_patterns[1] = 3'b000;
		green_patterns[2] = 3'b101;
		end
	 4'b0101:begin  //5
		green_patterns[0] = 3'b101;
		green_patterns[1] = 3'b010;
		green_patterns[2] = 3'b101;
		end
	 4'b0110:begin  //6
		green_patterns[0] = 3'b111;
		green_patterns[1] = 3'b000;
		green_patterns[2] = 3'b111;
	   end
	 4'b0111:begin   //7
		green_patterns[0] = 3'b111;
		green_patterns[1] = 3'b010;
		green_patterns[2] = 3'b111;
		end
	 4'b1000:begin    //8
		green_patterns[0] = 3'b111;
		green_patterns[1] = 3'b101;
		green_patterns[2] = 3'b111;
		end
	 4'b1001:begin    //9
		green_patterns[0] = 3'b111;
		green_patterns[1] = 3'b111;
		green_patterns[2] = 3'b111;
		end
	 default:begin
		green_patterns[0] = 3'b000;
		green_patterns[1] = 3'b000;
		green_patterns[2] = 3'b000;
		end
	 endcase
end

    // 行扫描逻辑
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            scan_index <= 3'd0;  // 初始化索引
        end else begin
				if(scan_index<3'b111)begin
					scan_index <= scan_index + 1;  // 每个时钟周期更新一行
				end
				else begin
					scan_index <= 3'b000;
				end
				if(sel < 2'b10)begin
					sel <= sel + 1 ;
				end
				else begin
					sel <= 2'b00;
				end
        end
    end
reg [2:0]flag;//计八个数
initial begin
	flag<=0;
end
	 
    // 显示点阵逻辑
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            row <= 8'b1111_1111;  // 所有行禁用
            r_col <= 8'b0000_0000; // 红色列全灭
				g_col <= 8'b0000_0000;
        end else begin
				if(flag==3'b000)begin
					row <= 8'b01111111; // 使用移位来进行赋值
					r_col[2:0] <= red_patterns[0];//将红色低三位赋值给列
					g_col <= 8'b0000_0000;
					flag <=flag +1 ;
				end
				if(flag==3'b001) begin
					row <= 8'b10111111;
					r_col[2:0] <= red_patterns[1];//将绿色高三位赋值给列信号
					flag <= flag+1;
					end
				if(flag==3'b010)begin
					row <= 8'b1101_1111;
					r_col[2:0] <= red_patterns[2];
					flag <= flag +1;
					end
				if(flag == 3'b011)begin
					row <= 8'b1110_1111;
					flag <= flag +1;
					r_col <= 8'b0000_0000;
				end
				if(flag == 3'b100)begin
					row <= 8'b1111_0111;
					flag <= flag+1;
				end
				if(flag ==3'b101)begin
					row <= 8'b1111_1011;
					g_col[7:5] <= green_patterns[0];
					flag <= flag+1;
				end
				if(flag == 3'b110)begin
					row <= 8'b1111_1101;
					g_col[7:5] <= green_patterns[1];
					flag <= flag+1;
				end
				if(flag == 3'b111)begin
					row <= 8'b1111_1110;
					g_col[7:5] <= green_patterns[2];
					flag <= 3'b000;
				end
        end 
    end

endmodule

测试模块 test

test 模块通过计数器周期性触发骰子更新。
时钟周期选择1kHz!

module test(                   //测试模块用于根据时钟信号,每0.2秒进行扔骰子操作
	 input clk, //时钟选择1kHz
    input wire rst,          // 复位信号
    output [3:0] dice1,   // 输出随机数(0-9)
	 output [3:0] dice2,
	 output reg clk_div
);

reg start;  //设置start信号,由时钟控制
reg [7:0] count;  //20计数器,即选择5位
reg cnt;


initial begin
	count <= 8'b0000_0000;
	start <= 1'b0;
	cnt <= 1'b0;
end

    // 实例化第二个随机数生成器
    random2 u_random2 (
        .clk(clk),
		  .rst(rst),        // 连接复位信号
        .roll(start),      // 连接掷骰子触发信号
        .dice(dice2)      // 连接第二个骰子的随机数输出
    );
	 
	 	     // 实例化第一个随机数生成器
    random u_random1 (
        .clk(clk),
		  .rst(rst),        // 连接复位信号
        .roll(start),      // 连接掷骰子触发信号
        .dice(dice1)      // 连接第一个骰子的随机数输出
    );

always @(posedge clk or posedge rst) begin
	clk_div <= start;
    if (rst) begin
        start <= 1'b0;
        count <= 8'b0;
    end else if (count < 8'd200) begin
        count <= count + 1;
        start <= 1'b0;
    end else begin
        count <= 8'b0;
        start <= 1'b1;  // 触发掷骰子
    end
end


endmodule

仿真模块

`timescale 1ms / 10ns

module tb_dice;

    // 输入信号
    reg clk;
    reg rst;
    reg start1,start2;

    // 输出信号
    wire [7:0] row;   // 行控制信号
    wire [7:0] r_col; // 红色列控制信号
    wire [7:0] g_col; // 绿色列控制信号
	 wire clk_div;

    // 内部信号(通过访问模块内部)
    wire [3:0] dice1; // 第一个骰子信号
    wire [3:0] dice2; // 第二个骰子信号

    // 实例化被测模块(DUT: Device Under Test)
    dice uut (
        .rst(rst),
        .clk(clk),
        .start1(start1),
		  .start2(start2),
        .row(row),
        .r_col(r_col),
        .g_col(g_col),
		  .clk_div(clk_div),
		  .dice1(dice1),
		  .dice2(dice2)
    );


    // 时钟生成器
    initial clk = 0;
    always #0.5 clk = ~clk; // 时钟周期 1ms

    // 仿真逻辑
    initial begin

        rst=0;
        #10000;
		  
		  rst = 1;
        #1;          // 等待 10ns
        
        rst = 0;      // 释放复位信号
        #1; 

        $stop;      // 结束仿真
    end

endmodule

引脚图

引脚图分配

总结

通过以上模块化设计,成功实现了双骰子的随机生成和点阵显示。
以下是博客的完整版本,包括推荐代码仓库的部分,用于分享您的代码:

仓库推荐

这是我们的 GitHub 仓库,仓库里有我们整理和归纳的其他北邮信通的资料,如果对您有用,还请您进入我们仓库给我们一个免费的star,这对我们很重要!

欢迎访问我们的代码仓库,获取更多示例与教程!

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芝麻柚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值