目录

​编辑

一、设计概述

二、设计模块

1、三阶魔方建模

(1)魔方基本操作:

(2)魔方建模:

2、魔方转动控制:

(1)控制概述:

(2)按键消抖:

(3)魔方控制:

3、HDMI显示模块:

(1)颜色编码转换:

(2)绘制魔方展开图和立方体:

(4)HDMI驱动IP例化:

(5)HDMI显示顶层模块:

4、顶层模块:

三、约束文件

1、键盘的管脚约束

2、HDMI TX端的管脚约束

3、完整约束文件

四、综合与上板验证

1、综合

2、上板效果

vivado工程的链接见文章最后

一、设计概述

通过对三阶魔方的建模,在FPGA上实现一个虚拟魔方,可以通过按键的组合来对模型进行旋转操作,对魔方操作的结果通过HDMI接口显示到显示器上。

开发板:Digilent ZYBO 7020

FPGA型号:ZYNQ xc7z020clg400-2

二、设计模块

1、三阶魔方建模

(1)魔方基本操作:

三阶魔方有六个面,分别是前面(Front)、后面(Behind)、左面(Left)、右面(Right)、上面(Up)、下面(Down),旋转一个面就用对应面的符号替代,这样方便了公式的记忆以及爱好者的交流。 对于魔方爱好者而言,魔方的转动有以下的操作与名称的对应图:

这样,每一种基本旋转就对应了一种符号表示。

本项目正是对三阶魔方的各种基本旋转进行建模,基本的旋转正确,则更为复杂的打乱也是正确的。

(2)魔方建模:

在FPGA这种硬件中色彩是可以使用一种二进制编码来表示的,标准的三阶魔方一共有六种颜色,又因为2^2<6<2^3,因此一种颜色使用一个3位的二进制编码来表示。又因为魔方一个面有9个色块,所以一共需要6(个面)*9(个色块)*3(位编码)=162位来表示一整个魔方的状态。我们所建模的魔方是红前橙后绿左蓝右白顶黄底的,为每一个色块分配一个3位编码来表示其颜色,我们得到了如下展开图:

使用了一个[161:0]的向量来表示整个魔方的状态,每个色块对应的颜色编码与向量索引的关系有了映射。3位颜色编码如下所示:

这样,就把魔方的旋转操作转化为了向量的位拼接运算操作,即每次旋转表征魔方状态的向量都重新赋值一次。例如顺时针90度的状态编码图:

同一个色块上面的索引是移动之前的向量索引,下面的是移动之后的向量索引,对应Verilog代码来说,18中旋转通过一个case语句来实现(KEY_VALUE是按键控制编码,不同的操作对应不同的按键编码,从而实现18种旋转),其代码如下:

这里使用了function来封装每一种操作,这样使得整个代码更加简洁易于维护。操作U对应的function代码如下:

初始状态:

function:

其他17种操作以此类推, 首先确定每一种操作的色块编码向量转移情况,然后再编写对应旋转的函数,这个建模的过程并不难,只是需要耐心和细心才能正确无误的写出每一种函数的状态编码转换。详细代码如下:

`timescale 1ns / 1ps
module CUBE(input clk,input rst_n,input [4:0]KEY_Value,//矩阵键盘控制转动output reg [161:0]cube_state//魔方状态:6*9*3);reg [161:0]cube_nstate;//暂存魔方下一个状态//魔方色块颜色定义parameter WHITE  = 3'b000;parameter GREEN  = 3'b001;parameter ORANGE = 3'b010;parameter BLUE   = 3'b011;parameter RED    = 3'b100;parameter YELLOW = 3'b101;//魔方状态转换always@(posedge clk or negedge rst_n)beginif(!rst_n)begincube_state <= {ORANGE,ORANGE,ORANGE,ORANGE,ORANGE,ORANGE,ORANGE,ORANGE,ORANGE,//BYELLOW,YELLOW,YELLOW,YELLOW,YELLOW,YELLOW,YELLOW,YELLOW,YELLOW,//DBLUE,BLUE,BLUE,BLUE,BLUE,BLUE,BLUE,BLUE,BLUE,                  //RRED,RED,RED,RED,RED,RED,RED,RED,RED,                           //FGREEN,GREEN,GREEN,GREEN,GREEN,GREEN,GREEN,GREEN,GREEN,         //LWHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE          //U};endelse begincube_state <= cube_nstate;endend//产生魔方下一个状态always@(*)begincase(KEY_Value)5'd0 :cube_nstate <= U(cube_state);5'd1 :cube_nstate <= D(cube_state);5'd2 :cube_nstate <= F(cube_state);5'd3 :cube_nstate <= B(cube_state);5'd4 :cube_nstate <= L(cube_state);5'd5 :cube_nstate <= R(cube_state);5'd6 :cube_nstate <= U2(cube_state);5'd7 :cube_nstate <= D2(cube_state);5'd8 :cube_nstate <= F2(cube_state);5'd9 :cube_nstate <= B2(cube_state);5'd10:cube_nstate <= L2(cube_state);5'd11:cube_nstate <= R2(cube_state);5'd12:cube_nstate <= Un(cube_state);5'd13:cube_nstate <= Dn(cube_state);5'd14:cube_nstate <= Fn(cube_state);5'd15:cube_nstate <= Bn(cube_state);5'd16:cube_nstate <= Ln(cube_state);5'd17:cube_nstate <= Rn(cube_state);default:cube_nstate <= cube_state;endcaseend/*--------------------------转动函数定义-------------------------------*/function [161:0]U(input [161:0]c);U = {c[29:27],c[32:30],c[35:33],c[152:150],c[149:147],c[146:144],c[143:141],c[140:138],c[137:135],c[134:108],//D面未动c[107:105],c[104:102],c[101:99],c[98:96],c[95:93],c[92:90],c[155:153],c[158:156],c[161:159],c[80:78],c[77:75],c[74:72],c[71:69],c[68:66],c[65:63],c[89:87],c[86:84],c[83:81],c[53:51],c[50:48],c[47:45],c[44:42],c[41:39],c[38:36],c[62:60],c[59:57],c[56:54],c[8:6],c[17:15],c[26:24],c[5:3],c[14:12],c[23:21],c[2:0],c[11:9],c[20:18]};endfunctionfunction [161:0]D(input [161:0]c);D = {c[161:159],c[158:156],c[155:153],c[152:150],c[149:147],c[146:144],c[101:99],c[104:102],c[107:105],c[116:114],c[125:123],c[134:132],c[113:111],c[122:120],c[131:129],c[110:108],c[119:117],c[128:126],c[80:78],c[77:75],c[74:72],c[98:96],c[95:93],c[92:90],c[89:87],c[86:84],c[83:81],c[53:51],c[50:48],c[47:45],c[71:69],c[68:66],c[65:63],c[62:60],c[59:57],c[56:54],c[137:135],c[140:138],c[143:141],c[44:42],c[41:39],c[38:36],c[35:33],c[32:30],c[29:27],c[26:0]//U面未动};endfunctionfunction [161:0]F(input [161:0]c);F = {c[161:135],//B面未动c[134:132],c[131:129],c[128:126],c[125:123],c[122:120],c[119:117],c[83:81],c[92:90],c[101:99],c[107:105],c[104:102],c[26:24],c[98:96],c[95:93],c[23:21],c[89:87],c[86:84],c[20:18],c[62:60],c[71:69],c[80:78],c[59:57],c[68:66],c[77:75],c[56:54],c[65:63],c[74:72],c[116:114],c[50:48],c[47:45],c[113:111],c[41:39],c[38:36],c[110:108],c[32:30],c[29:27],c[35:33],c[44:42],c[53:51],c[17:15],c[14:12],c[11:9],c[8:6],c[5:3],c[2:0]};endfunctionfunction [161:0]B(input [161:0]c);B = {c[143:141],c[152:150],c[161:159],c[140:138],c[149:147],c[158:156],c[137:135],c[146:144],c[155:153],c[47:45],c[38:36],c[29:27],c[125:123],c[122:120],c[119:117],c[116:114],c[113:111],c[110:108],c[128:126],c[104:102],c[101:99],c[131:129],c[95:93],c[92:90],c[134:132],c[86:84],c[83:81],c[80:54],//F面未动c[53:51],c[50:48],c[2:0],c[44:42],c[41:39],c[5:3],c[35:33],c[32:30],c[8:6],c[26:24],c[23:21],c[20:18],c[17:15],c[14:12],c[11:9],c[107:105],c[98:96],c[89:87]};endfunctionfunction [161:0]L(input [161:0]c);L = {c[161:159],c[158:156],c[128:126],c[152:150],c[149:147],c[119:117],c[143:141],c[140:138],c[110:108],c[134:132],c[131:129],c[74:72],c[125:123],c[122:120],c[65:63],c[116:114],c[113:111],c[56:54],c[107:81],//R面未动c[80:78],c[77:75],c[20:18],c[71:69],c[68:66],c[11:9],c[62:60],c[59:57],c[2:0],c[35:33],c[44:42],c[53:51],c[32:30],c[41:39],c[50:48],c[29:27],c[38:36],c[47:45],c[26:24],c[23:21],c[155:153],c[17:15],c[14:12],c[146:144],c[8:6],c[5:3],c[137:135]};endfunctionfunction [161:0]R(input [161:0]c);R = {c[26:24],c[158:156],c[155:153],c[17:15],c[149:147],c[146:144],c[8:6],c[140:138],c[137:135],c[161:159],c[131:129],c[128:126],c[152:150],c[122:120],c[119:117],c[143:141],c[113:111],c[110:108],c[89:87],c[98:96],c[107:105],c[86:84],c[95:93],c[104:102],c[83:81],c[92:90],c[101:99],c[134:132],c[77:75],c[74:72],c[125:123],c[68:66],c[65:63],c[116:114],c[59:57],c[56:54],c[53:27],//L面未动c[80:78],c[23:21],c[20:18],c[71:69],c[14:12],c[11:9],c[62:60],c[5:3],c[2:0]};endfunctionfunction [161:0]U2(input [161:0]c);U2 = {c[56:54],c[59:57],c[62:60],c[152:150],c[149:147],c[146:144],c[143:141],c[140:138],c[137:135],c[134:108],//D面未动c[107:105],c[104:102],c[101:99],c[98:96],c[95:93],c[92:90],c[35:33],c[32:30],c[29:27],c[80:78],c[77:75],c[74:72],c[71:69],c[68:66],c[65:63],c[155:153],c[158:156],c[161:159],c[53:51],c[50:48],c[47:45],c[44:42],c[41:39],c[38:36],c[89:87],c[86:84],c[83:81],c[2:0],c[5:3],c[8:6],c[11:9],c[14:12],c[17:15],c[20:18],c[23:21],c[26:24]};endfunctionfunction [161:0]D2(input [161:0]c);D2 = {c[161:159],c[158:156],c[155:153],c[152:150],c[149:147],c[146:144],c[74:72],c[77:75],c[80:78],c[110:108],c[113:111],c[116:114],c[119:117],c[122:120],c[125:123],c[128:126],c[131:129],c[134:132],c[53:51],c[50:48],c[47:45],c[98:96],c[95:93],c[92:90],c[89:87],c[86:84],c[83:81],c[137:135],c[140:138],c[143:141],c[71:69],c[68:66],c[65:63],c[62:60],c[59:57],c[56:54],c[107:105],c[104:102],c[101:99],c[44:42],c[41:39],c[38:36],c[35:33],c[32:30],c[29:27],c[26:0]//U面未动};endfunctionfunction [161:0]F2(input [161:0]c);F2 = {c[161:135],//B面未动c[134:132],c[131:129],c[128:126],c[125:123],c[122:120],c[119:117],c[20:18],c[23:21],c[26:24],c[107:105],c[104:102],c[35:33],c[98:96],c[95:93],c[44:42],c[89:87],c[86:84],c[53:51],c[56:54],c[59:57],c[59:57],c[65:63],c[68:66],c[71:69],c[74:72],c[77:75],c[80:78],c[83:81],c[50:48],c[47:45],c[92:90],c[41:39],c[38:36],c[101:99],c[32:30],c[29:27],c[110:108],c[113:111],c[116:114],c[17:15],c[14:12],c[11:9],c[8:6],c[5:3],c[2:0]};endfunctionfunction [161:0]B2(input [161:0]c);B2 = {c[137:135],c[140:138],c[143:141],c[146:144],c[149:147],c[152:150],c[155:153],c[158:156],c[161:159],c[2:0],c[5:3],c[8:6],c[125:123],c[122:120],c[119:117],c[116:114],c[113:111],c[110:108],c[29:27],c[104:102],c[101:99],c[38:36],c[95:93],c[92:90],c[47:45],c[86:84],c[83:81],c[80:54],//F面未动c[53:51],c[50:48],c[89:87],c[44:42],c[41:39],c[98:96],c[35:33],c[32:30],c[107:105],c[26:24],c[23:21],c[20:18],c[17:15],c[14:12],c[11:9],c[128:126],c[131:129],c[134:132]};endfunctionfunction [161:0]L2(input [161:0]c);L2 = {c[161:159],c[158:156],c[74:72],c[152:150],c[149:147],c[65:63],c[143:141],c[140:138],c[56:54],c[134:132],c[131:129],c[20:18],c[125:123],c[122:120],c[11:9],c[116:114],c[113:111],c[2:0],c[107:81],//R面未动c[80:78],c[77:75],c[155:153],c[71:69],c[68:66],c[146:144],c[62:60],c[59:57],c[137:135],c[29:27],c[32:30],c[35:33],c[38:36],c[41:39],c[44:42],c[47:45],c[50:48],c[53:51],c[26:24],c[23:21],c[128:126],c[17:15],c[14:12],c[119:117],c[8:6],c[5:3],c[110:108]};endfunctionfunction [161:0]R2(input [161:0]c);R2 = {c[80:78],c[158:156],c[155:153],c[71:69],c[149:147],c[146:144],c[62:60],c[140:138],c[137:135],c[26:24],c[131:129],c[128:126],c[17:15],c[122:120],c[119:117],c[8:6],c[113:111],c[110:108],c[89:87],c[86:84],c[83:81],c[92:90],c[95:93],c[98:96],c[101:99],c[104:102],c[107:105],c[161:159],c[77:75],c[74:72],c[152:150],c[68:66],c[65:63],c[143:141],c[59:57],c[56:54],c[53:27],//L面未动c[134:132],c[23:21],c[20:18],c[125:123],c[14:12],c[11:9],c[116:114],c[5:3],c[2:0]};endfunctionfunction [161:0]Un(input [161:0]c);Un = {c[83:81],c[86:84],c[89:87],c[152:150],c[149:147],c[146:144],c[143:141],c[140:138],c[137:135],c[134:108],//D面未动c[107:105],c[104:102],c[101:99],c[98:96],c[95:93],c[92:90],c[62:60],c[59:57],c[56:54],c[80:78],c[77:75],c[74:72],c[71:69],c[68:66],c[65:63],c[35:33],c[32:30],c[29:27],c[53:51],c[50:48],c[47:45],c[44:42],c[41:39],c[38:36],c[155:153],c[158:156],c[161:159],c[20:18],c[11:9],c[2:0],c[23:21],c[14:12],c[5:3],c[26:24],c[17:15],c[8:6]};endfunctionfunction [161:0]Dn(input [161:0]c);Dn = {c[161:159],c[158:156],c[155:153],c[152:150],c[149:147],c[146:144],c[47:45],c[50:48],c[53:51],c[128:126],c[131:129],c[110:108],c[131:129],c[122:120],c[113:111],c[134:132],c[125:123],c[116:114],c[137:135],c[140:138],c[143:141],c[98:96],c[95:93],c[92:90],c[89:87],c[86:84],c[83:81],c[107:105],c[104:102],c[101:99],c[71:69],c[68:66],c[65:63],c[62:60],c[59:57],c[56:54],c[80:78],c[77:75],c[74:72],c[44:42],c[41:39],c[38:36],c[35:33],c[32:30],c[29:27],c[26:0]//U面未动};endfunctionfunction [161:0]Fn(input [161:0]c);Fn = {c[161:135],//B面未动c[134:132],c[131:129],c[128:126],c[125:123],c[122:120],c[119:117],c[53:51],c[44:42],c[35:33],c[107:105],c[104:102],c[110:108],c[98:96],c[95:93],c[113:111],c[89:87],c[86:84],c[116:114],c[74:72],c[65:63],c[56:54],c[77:75],c[68:66],c[59:57],c[80:78],c[71:69],c[62:60],c[20:18],c[50:48],c[47:45],c[23:21],c[41:39],c[38:36],c[26:24],c[32:30],c[29:27],c[101:99],c[92:90],c[83:81],c[17:15],c[14:12],c[11:9],c[8:6],c[5:3],c[2:0]};endfunctionfunction [161:0]Bn(input [161:0]c);Bn = {c[155:153],c[146:144],c[137:135],c[158:156],c[149:147],c[140:138],c[161:159],c[152:150],c[143:141],c[89:87],c[98:96],c[107:105],c[125:123],c[122:120],c[119:117],c[116:114],c[113:111],c[110:108],c[8:6],c[104:102],c[101:99],c[5:3],c[95:93],c[92:90],c[2:0],c[86:84],c[83:81],c[80:54],//F面未动c[53:51],c[50:48],c[134:132],c[44:42],c[41:39],c[131:129],c[35:33],c[32:30],c[128:126],c[26:24],c[23:21],c[20:18],c[17:15],c[14:12],c[11:9],c[29:27],c[38:36],c[47:45]};endfunctionfunction [161:0]Ln(input [161:0]c);Ln = {c[161:159],c[158:156],c[20:18],c[152:150],c[149:147],c[11:9],c[143:141],c[140:138],c[2:0],c[134:132],c[131:129],c[155:153],c[125:123],c[122:120],c[146:144],c[116:114],c[113:111],c[137:135],c[107:81],//R面未动c[80:78],c[77:75],c[128:126],c[71:69],c[68:66],c[119:117],c[62:60],c[59:57],c[110:108],c[47:45],c[38:36],c[29:27],c[50:48],c[41:39],c[32:30],c[53:51],c[44:42],c[35:33],c[26:24],c[23:21],c[74:72],c[17:15],c[14:12],c[65:63],c[8:6],c[5:3],c[56:54]};endfunctionfunction [161:0]Rn(input [161:0]c);Rn = {c[134:132],c[158:156],c[155:153],c[125:123],c[149:147],c[146:144],c[116:114],c[140:138],c[137:135],c[80:78],c[131:129],c[128:126],c[71:69],c[122:120],c[119:117],c[62:60],c[113:111],c[110:108],c[101:99],c[92:90],c[83:81],c[104:102],c[95:93],c[86:84],c[107:105],c[98:96],c[89:87],c[26:24],c[77:75],c[74:72],c[17:15],c[68:66],c[65:63],c[8:6],c[59:57],c[56:54],c[53:27],//L面未动c[161:159],c[23:21],c[20:18],c[152:150],c[14:12],c[11:9],c[143:141],c[5:3],c[2:0]};endfunctionendmodule

2、魔方转动控制:

(1)控制概述:

由于使用的ZYBO开发板只有4个拨码开关和4个独立按键,这对于我们一共18种基本旋转操作来说是不够用的,于是我们制作了一个有6个独立按键的PCB键盘,加上2个拨码开关,以拨码开关控制旋转的角度是顺时针90°、180°还是逆时针90°,以按键控制UDFBLR六个面哪个面被旋转。原理图、PCB、实物图如下:

(2)按键消抖:

由于独立按键种弹簧片的抖动会使电路误触发,因此需要按键消抖模块滤除抖动,这里挖个坑会更新一个按键消抖模块的教程,先放出按键消抖代码:

module KeyPress(input clk,input rst_n,input KEY_IN,output reg KEY_FLAG,output reg KEY_STATE
);reg key_reg_0, key_reg_1;//打两拍异步转同步reg en_cnt, cnt_full;reg [3:0]state;reg [19:0]cnt;wire flag_H2L, flag_L2H;localparamKey_up         =   4'b0001,Filter_Up2Down  =   4'b0010,Key_down        =   4'b0100,Filter_Down2Up  =   4'b1000;//======判断按键输入信号跳变沿========//always @(posedge clk or negedge rst_n)if(!rst_n)beginkey_reg_0 <= 1'b0;key_reg_1 <= 1'b0;endelsebeginkey_reg_0 <= KEY_IN;key_reg_1 <= key_reg_0;endassign flag_H2L = key_reg_1 && (!key_reg_0);assign flag_L2H = (!key_reg_1) && key_reg_0;//============计数使能模块==========//always @(posedge clk or negedge rst_n)if(!rst_n)cnt <= 1'b0;else if(en_cnt)cnt <= cnt + 1'b1;elsecnt <= 1'b0;//=============计数模块=============//always @(posedge clk or negedge rst_n)if(!rst_n)cnt_full <= 1'b0;else if(cnt == 20'd999_999)cnt_full <= 1'b1;elsecnt_full <= 1'b0;//=============有限状态机============//always @(posedge clk or negedge rst_n)if(!rst_n)beginen_cnt <= 1'b0;state <= Key_up;KEY_FLAG <= 1'b0;KEY_STATE <= 1'b1;endelsecase(state)//保持没按Key_up: begin KEY_FLAG <= 1'b0;if(flag_H2L) beginstate <= Filter_Up2Down;en_cnt <= 1'b1;endelsestate <= Key_up;                         end//正在向下按  Filter_Up2Down: beginif(cnt_full) beginen_cnt <= 1'b0;state <= Key_down;KEY_STATE <= 1'b0;KEY_FLAG <= 1'b1;endelse if(flag_L2H) beginen_cnt <= 1'b0;state <= Key_up;endelsestate <= Filter_Up2Down;end//保持按下状态Key_down: beginKEY_FLAG <= 1'b0;if(flag_L2H) beginstate <= Filter_Down2Up;en_cnt <= 1'b1;endelse state <= Key_down;end//正在释放按键Filter_Down2Up: beginif(cnt_full) beginen_cnt <= 1'b0;state <= Key_up;KEY_FLAG <= 1'b1;KEY_STATE <= 1'b1;endelse if(flag_H2L) beginen_cnt <= 1'b0;state <= Key_down;end                      elsestate <= Filter_Down2Up;end//其他未定义状态default: beginen_cnt <= 1'b0;state <= Key_up;KEY_FLAG <= 1'b0;KEY_STATE <= 1'b1;endendcase   endmodule

(3)魔方控制:

六个独立按键先经过消抖之后产生正确的信号,结合2个拨码开关的状态,使用一个case语句就能实现魔方状态的控制:

每一种组合对应一个KEY_VALUE,然后KEY_VALUE对应魔方模块中一种旋转操作√。完整代码如下:

module cube_ctrl(input clk,input rst_n,input [1:0]rotate_mode,//00->顺90度,01->180度,11->逆90度input [5:0]key_n,output reg[4:0]KEY_Value);wire [5:0]KEY_STATE,KEY_FLAG;//模块例化KeyPress k0(.clk(clk),.rst_n(rst_n),.KEY_IN(key_n[0]),.KEY_FLAG(KEY_FLAG[0]),.KEY_STATE(KEY_STATE[0]));KeyPress k1(.clk(clk),.rst_n(rst_n),.KEY_IN(key_n[1]),.KEY_FLAG(KEY_FLAG[1]),.KEY_STATE(KEY_STATE[1]));KeyPress k2(.clk(clk),.rst_n(rst_n),.KEY_IN(key_n[2]),.KEY_FLAG(KEY_FLAG[2]),.KEY_STATE(KEY_STATE[2]));KeyPress k3(.clk(clk),.rst_n(rst_n),.KEY_IN(key_n[3]),.KEY_FLAG(KEY_FLAG[3]),.KEY_STATE(KEY_STATE[3]));KeyPress k4(.clk(clk),.rst_n(rst_n),.KEY_IN(key_n[4]),.KEY_FLAG(KEY_FLAG[4]),.KEY_STATE(KEY_STATE[4]));KeyPress k5(.clk(clk),.rst_n(rst_n),.KEY_IN(key_n[5]),.KEY_FLAG(KEY_FLAG[5]),.KEY_STATE(KEY_STATE[5]));//KEY_VALUE译码always@(posedge clk or negedge rst_n)beginif(!rst_n)beginKEY_Value <= 5'd18;endelse if(KEY_FLAG != 6'b000000)begincase({rotate_mode,KEY_STATE})8'b00_111110:KEY_Value <= 5'd0; //U8'b00_111101:KEY_Value <= 5'd1; //D8'b00_111011:KEY_Value <= 5'd2; //F8'b00_110111:KEY_Value <= 5'd3; //B8'b00_101111:KEY_Value <= 5'd4; //L8'b00_011111:KEY_Value <= 5'd5; //R8'b01_111110:KEY_Value <= 5'd6; //2U8'b01_111101:KEY_Value <= 5'd7; //2D8'b01_111011:KEY_Value <= 5'd8; //2F8'b01_110111:KEY_Value <= 5'd9; //2B8'b01_101111:KEY_Value <= 5'd10;//2L8'b01_011111:KEY_Value <= 5'd11;//2R8'b11_111110:KEY_Value <= 5'd12;//U'8'b11_111101:KEY_Value <= 5'd13;//D'8'b11_111011:KEY_Value <= 5'd14;//F'8'b11_110111:KEY_Value <= 5'd15;//B'8'b11_101111:KEY_Value <= 5'd16;//L'8'b11_011111:KEY_Value <= 5'd17;//R'default:KEY_Value <= 5'd18;endcaseendelse beginKEY_Value <= 5'd18;endend
endmodule

3、HDMI显示模块:

本项目使用到了Digilent官方的HDMI接口的IP,视频信号产生的原理与VGA接口相同,将视频信号输入HDMI的驱动IP转化为TMDS信号输出显示到显示器上。这里同样挖一个坑,我会单独出一个HDMI接口驱动的教程,这里仅针对本实验用到的魔方立体图和展开图的绘制做一个说明。

(1)颜色编码转换:

我们在medule cube中使用了一个[161:0]cube_state向量来表示魔方的状态,一个色块采用3位编码来表示其颜色,但是HDMI显示是采用RGB888编码格式的,一种颜色使用(R,G,B)三原色组成,一个颜色通道使用8位二进制数表示2^8=128中颜色深度,因此我们需要将cube中3位颜色编码对RGB888编码进行一个转换,这使用一个函数function来实现:

(2)绘制魔方展开图和立方体:

图像在显示器上的显示是通过行扫描和场扫描来实现的,如果我们要在显示器特定位置显示一个图案,就先得确定图案在显示器上的坐标,通过行扫描、场扫描计数器的方式在特定的像素输出显示特定的颜色,这样就是实现了图案的显示。

我们使用的显示器分辨率为1440*900,水平扫描频率为56KHz,垂直扫描频率60Hz。根据以上信息我们定义了一系列的参数,并使用水平扫描计数器和垂直扫描计数器在特定位置绘制图像,有如下效果:

参数定义如下:

对于行扫描和场扫描,有水平和垂直扫描参数定义如下:

对于魔方展开图来说,其色块边界、大小以及位置定义如下:

对立方体图来说,其色块边界、大小以及位置定义如下:

首先设置寄存器暂存RGB三种颜色的8位编码:

声明行同步信号发生器和场同步信号发生器:

然后就如同VGA或HDMI协议中绘制图案那样,在行扫描计数器和列扫描计数器达到特定数值,即达到特定像素的时候显示特定的颜色,这通过一系列条件判断语句来实现,具体代码如下:

最后发送VGA输出信号

(这里使用的是VGA显示原理产生数据,在通过HDMI驱动IP来转化位TMDS信号输出)完整代码如下:

module hdmi_data_gen(// input clk,input rst_n,input pix_clk,input [4:0]KEY_Value,//矩阵键盘控制转动output [7:0]VGA_R,output [7:0]VGA_G,output [7:0]VGA_B,output VGA_HS,output VGA_VS,output VGA_DE);/*-------------------3bit色彩编码转RGB888编码---------------------*/function [23:0]color_rgb(input [2:0]code);//RGB色彩编码parameter WHITE = 24'hFFFFFF;parameter GREEN = 24'h008000;parameter ORANGE= 24'hFFA500;parameter BLUE  = 24'h0000FF;parameter RED   = 24'hFF0000;parameter YELLOW= 24'hFFFF00;parameter BLACK = 24'h000000;//编码转化case(code)3'b000: color_rgb = WHITE;3'b001: color_rgb = GREEN;3'b010: color_rgb = ORANGE;3'b011: color_rgb = BLUE;3'b100: color_rgb = RED;3'b101: color_rgb = YELLOW;default:color_rgb = BLACK;endcaseendfunction//---------------------------------//// 水平扫描参数的设定1280*720  60HZ//--------------------------------//parameter H_Total       =   1680;//eparameter H_Sync        =   136; //aparameter H_Back        =   200; //bparameter H_Active      =   1280;//cparameter H_Front       =   64;  //dparameter H_Start       =   336;parameter H_End         =   1616;//-------------------------------//// 垂直扫描参数的设定1280*720    60HZ    //-------------------------------//parameter V_Total        =   828;parameter V_Sync        =   3;parameter V_Back      =   24;parameter V_Active       =   800;parameter V_Front       =   1;parameter V_Start     =   27;parameter V_End          =   827;//行同步信号发生器reg[11:0] x_cnt;always @(posedge pix_clk)beginif(x_cnt == H_Total)x_cnt <= 1;elsex_cnt <= x_cnt + 1;end//场同步信号发生器reg[11:0]  y_cnt;always @(posedge pix_clk)beginif(y_cnt == V_Total)y_cnt <= 1;else if(x_cnt == H_Total)y_cnt <= y_cnt + 1;endreg [10:0]cur_x;reg [10:0]cur_y;always @(posedge pix_clk) begincur_x <= (x_cnt < H_Sync + H_Back) ? 11'b0 : (x_cnt - H_Sync - H_Back);cur_y <= (y_cnt < V_Sync + V_Back) ? 11'b0 : (y_cnt - V_Sync - V_Back);endwire  hs_de = (x_cnt<H_Start)? 0:(x_cnt<=H_End)?1:0;//行消隐控制wire  vs_de = (y_cnt<V_Start)? 0:(y_cnt<=V_End)?1:0;//列消隐控制/*------------------------------虚拟魔方模块实例化----------------------------*/wire [2:0]cube[0:5][0:8];CUBE Cube(.clk(pix_clk),.rst_n(rst_n),.KEY_Value(KEY_Value),//矩阵键盘控制转动.cube_state({cube[5][8],cube[5][7],cube[5][6],cube[5][5],cube[5][4],cube[5][3],cube[5][2],cube[5][1],cube[5][0],//Bcube[4][8],cube[4][7],cube[4][6],cube[4][5],cube[4][4],cube[4][3],cube[4][2],cube[4][1],cube[4][0],//Dcube[3][8],cube[3][7],cube[3][6],cube[3][5],cube[3][4],cube[3][3],cube[3][2],cube[3][1],cube[3][0],//Rcube[2][8],cube[2][7],cube[2][6],cube[2][5],cube[2][4],cube[2][3],cube[2][2],cube[2][1],cube[2][0],//Fcube[1][8],cube[1][7],cube[1][6],cube[1][5],cube[1][4],cube[1][3],cube[1][2],cube[1][1],cube[1][0],//Lcube[0][8],cube[0][7],cube[0][6],cube[0][5],cube[0][4],cube[0][3],cube[0][2],cube[0][1],cube[0][0] //U})//魔方状态:6*9*3);//寄存RGB颜色编码reg [7:0]O_red, O_green, O_blue;// 功能:画出魔方展开图和立体图1024*768---------------------------------parameter FLAT_LX     =   11'd906;//650;parameter FLAT_UY     =   11'd430;parameter BLOCK_SIZ   =   11'd25;parameter FACE_SIZ    =   11'd75;parameter FACE_SIZ_2  =   11'd150;parameter FACE_SIZ_3  =   11'd225;parameter FACE_SIZ_4  =   11'd300;parameter EDGE_COL    =   24'h73E68C;//灰边parameter FLAT_BGC    =   24'h000000;//黑色背景parameter REAL_LX     =   11'd356;parameter REAL_UY     =   11'd200;parameter REAL_SZ     =   11'd40;parameter REAL_SZ_2   =   2*REAL_SZ;parameter REAL_SZ_3   =   3*REAL_SZ;parameter REAL_SZ_4   =   4*REAL_SZ;parameter REAL_SZ_5   =   5*REAL_SZ;parameter REAL_SZ_6   =   6*REAL_SZ;parameter REAL_SZ_7   =   7*REAL_SZ;parameter REAL_SZ_8   =   8*REAL_SZ;parameter REAL_SZ_9   =   9*REAL_SZ;parameter REAL_SZ_11  =   11*REAL_SZ;parameter REAL_SZ_13  =   13*REAL_SZ;parameter REAL_SZ_15  =   15*REAL_SZ;parameter REAL_BGC    =   24'h000000;//黑色背景wire [10:0]tmp_rx;wire [10:0]tmp_ry;wire [10:0]tmp_rxy;assign tmp_rx   = cur_x - REAL_LX;assign tmp_ry   = cur_y - REAL_UY;assign tmp_rxy  = cur_x + cur_y - REAL_LX - REAL_UY;always @(posedge pix_clk) begin// 展开图if (cur_x >= FLAT_LX && cur_y >= FLAT_UY) begin// 大边框-行if (cur_y == (FLAT_UY) || cur_y == (FLAT_UY + FACE_SIZ_3) || cur_y == (FLAT_UY + FACE_SIZ_4)) begin{O_red, O_green, O_blue} <= (((cur_x >= FLAT_LX + FACE_SIZ) && (cur_x <= FLAT_LX + FACE_SIZ_2)) ? EDGE_COL : FLAT_BGC);    endelse if (cur_y == (FLAT_UY + FACE_SIZ) || cur_y == (FLAT_UY + FACE_SIZ_2)) begin{O_red, O_green, O_blue} <= (((cur_x <= FLAT_LX + FACE_SIZ_3)) ? EDGE_COL : FLAT_BGC);end// 大边框-列else if (cur_x == (FLAT_LX) || cur_x == (FLAT_LX + FACE_SIZ_3)) begin{O_red, O_green, O_blue} <= (((cur_y >= FLAT_UY + FACE_SIZ) && (cur_y <= FLAT_UY + FACE_SIZ_2)) ? EDGE_COL : FLAT_BGC);endelse if (cur_x == (FLAT_LX + FACE_SIZ) || cur_x == (FLAT_LX + FACE_SIZ_2)) begin{O_red, O_green, O_blue} <= (((cur_y <= FLAT_UY + FACE_SIZ_4)) ? EDGE_COL : FLAT_BGC);end// 内颜色else if (cur_y < FLAT_UY + FACE_SIZ) beginif (cur_x > FLAT_LX + FACE_SIZ && cur_x < FLAT_LX + FACE_SIZ_2) begin{O_red, O_green, O_blue} <= color_rgb(cube[0][( (cur_x-(FLAT_LX+FACE_SIZ))/BLOCK_SIZ + (cur_y-(FLAT_UY))/BLOCK_SIZ*3 )]);//Uendelse begin{O_red, O_green, O_blue} <= FLAT_BGC;endendelse if (cur_y < FLAT_UY + FACE_SIZ_2) beginif (cur_x < FLAT_LX + FACE_SIZ) begin{O_red, O_green, O_blue} <= color_rgb(cube[1][( (cur_x-(FLAT_LX))/BLOCK_SIZ + (cur_y-(FLAT_UY+FACE_SIZ))/BLOCK_SIZ*3 )]);//Lendelse if (cur_x < FLAT_LX + FACE_SIZ_2) begin{O_red, O_green, O_blue} <= color_rgb(cube[2][( (cur_x-(FLAT_LX+FACE_SIZ))/BLOCK_SIZ + (cur_y-(FLAT_UY+FACE_SIZ))/BLOCK_SIZ*3 )]);//Fendelse if (cur_x < FLAT_LX + FACE_SIZ_3) begin{O_red, O_green, O_blue} <= color_rgb(cube[3][( (cur_x-(FLAT_LX+FACE_SIZ_2))/BLOCK_SIZ + (cur_y-(FLAT_UY+FACE_SIZ))/BLOCK_SIZ*3 )]);//Rendelse begin{O_red, O_green, O_blue} <= FLAT_BGC;endendelse if (cur_y < FLAT_UY + FACE_SIZ_3) beginif (cur_x > FLAT_LX + FACE_SIZ && cur_x < FLAT_LX + FACE_SIZ_2) begin{O_red, O_green, O_blue} <= color_rgb(cube[4][( (cur_x-(FLAT_LX+FACE_SIZ))/BLOCK_SIZ + (cur_y-(FLAT_UY+FACE_SIZ_2))/BLOCK_SIZ*3 )]);//Dendelse begin{O_red, O_green, O_blue} <= FLAT_BGC;end        endelse if (cur_y < FLAT_UY + FACE_SIZ_4) beginif (cur_x > FLAT_LX + FACE_SIZ && cur_x < FLAT_LX + FACE_SIZ_2) begin{O_red, O_green, O_blue} <= color_rgb(cube[5][( (cur_x-(FLAT_LX+FACE_SIZ))/BLOCK_SIZ + (cur_y-(FLAT_UY+FACE_SIZ_3))/BLOCK_SIZ*3 )]);//Bendelse begin{O_red, O_green, O_blue} <= FLAT_BGC;end        endelse begin{O_red, O_green, O_blue} <= FLAT_BGC;endend// 立体图else if (cur_x >= REAL_LX && cur_x <= REAL_LX+REAL_SZ_9 && cur_y >= REAL_UY && cur_y <= REAL_UY+REAL_SZ_9) beginif (((tmp_rx == 0 || tmp_rx == REAL_SZ_2 || tmp_rx == REAL_SZ_4 || tmp_rx == REAL_SZ_6) && tmp_ry >= REAL_SZ_3) ||((tmp_rx == REAL_SZ_7 || tmp_rx == REAL_SZ_8 || tmp_rx == REAL_SZ_9) && tmp_rxy >= REAL_SZ_9 && tmp_rxy <= REAL_SZ_15) ||((tmp_ry == 0 || tmp_ry == REAL_SZ || tmp_ry == REAL_SZ_2 || tmp_ry == REAL_SZ_3) && tmp_rxy >= REAL_SZ_3 && tmp_rxy <= REAL_SZ_9) ||((tmp_ry == REAL_SZ_5 || tmp_ry == REAL_SZ_7 || tmp_ry == REAL_SZ_9) && tmp_rx <= REAL_SZ_6) ||((tmp_rxy == REAL_SZ_3 || tmp_rxy == REAL_SZ_5 || tmp_rxy == REAL_SZ_7 || tmp_rxy == REAL_SZ_9) && tmp_ry <= REAL_SZ_3) ||((tmp_rxy == REAL_SZ_11 || tmp_rxy == REAL_SZ_13 || tmp_rxy == REAL_SZ_15) && tmp_rx >= REAL_SZ_6)) begin{O_red, O_green, O_blue} <= EDGE_COL;endelse if (tmp_ry < REAL_SZ_3) beginif (tmp_rxy < REAL_SZ_3) begin{O_red, O_green, O_blue} <= REAL_BGC;endelse if (tmp_rxy < REAL_SZ_9) begin{O_red, O_green, O_blue} <= color_rgb(cube[0][ (tmp_rxy-REAL_SZ_3)/REAL_SZ_2 + (tmp_ry/REAL_SZ)*3 ]);//Uendelse begin{O_red, O_green, O_blue} <= color_rgb(cube[3][ (tmp_rx-REAL_SZ_6)/REAL_SZ + (tmp_rxy - REAL_SZ_9)/REAL_SZ_2*3 ]);//Rendendelse beginif (tmp_rx < REAL_SZ_6) begin{O_red, O_green, O_blue} <= color_rgb(cube[2][ (tmp_rx)/REAL_SZ_2 + (tmp_ry-REAL_SZ_3)/REAL_SZ_2*3 ]);//Fendelse if (tmp_rxy < REAL_SZ_15) begin{O_red, O_green, O_blue} <= color_rgb(cube[3][ (tmp_rx-REAL_SZ_6)/REAL_SZ + (tmp_rxy - REAL_SZ_9)/REAL_SZ_2*3 ]);//R{O_red, O_green, O_blue} <= color_rgb(cube[3][ (tmp_rx-REAL_SZ_6)/REAL_SZ + (tmp_rxy - REAL_SZ_9)/REAL_SZ_2*3 ]);//Rendelse begin{O_red, O_green, O_blue} <= REAL_BGC;endendendelse begin{O_red, O_green, O_blue} <= REAL_BGC;endend// 功能:画出魔方展开图和立体图-----------------------------------------assign VGA_HS = (x_cnt==12'd0)? 1:(x_cnt<H_Sync)? 0 : 1;assign VGA_VS = (y_cnt==12'd0)? 1:(y_cnt<V_Sync)? 0 : 1;assign VGA_DE = hs_de &   vs_de;assign VGA_R  = (hs_de & vs_de) ? O_red  : 8'h0;assign VGA_G  = (hs_de & vs_de) ? O_green: 8'h0;assign VGA_B  = (hs_de & vs_de) ? O_blue : 8'h0;endmodule

(4)HDMI驱动IP例化:

不需要配置任何参数,直接例化即可。

(5)HDMI显示顶层模块:

将hdmi_data_gen 产生的信号传输到HDMI的驱动IP中,将TMDS的信号输出。

module HDMI_display(input clk_100M,input rst_n,input [4:0]KEY_Value,output HDMI_CLK_P,output HDMI_CLK_N,output HDMI_D2_P,output HDMI_D2_N,output HDMI_D1_P,output HDMI_D1_N,output HDMI_D0_P,output HDMI_D0_N,output pixclk
);// wire pixclk;wire[7:0]   R,G,B;wire HS,VS,DE;hdmi_data_gen u_hdmi_data_gen(// .clk(clk_100M),.rst_n(rst_n),.KEY_Value(KEY_Value),.pix_clk            (pixclk),.VGA_R              (R),.VGA_G              (G),.VGA_B              (B),.VGA_HS             (HS),.VGA_VS             (VS),.VGA_DE             (DE));wire serclk;wire lock;wire[23:0]  RGB;assign RGB={R,G,B};HDMI_FPGA_ML_0 u_HDMI(.PXLCLK_I           (pixclk),.PXLCLK_5X_I        (serclk),.LOCKED_I           (lock),.RST_N              (1'b1),.VGA_HS             (HS),.VGA_VS             (VS),.VGA_DE             (DE),.VGA_RGB            (RGB),.HDMI_CLK_P         (HDMI_CLK_P),.HDMI_CLK_N         (HDMI_CLK_N),.HDMI_D2_P          (HDMI_D2_P),.HDMI_D2_N          (HDMI_D2_N),.HDMI_D1_P          (HDMI_D1_P),.HDMI_D1_N          (HDMI_D1_N),.HDMI_D0_P          (HDMI_D0_P),.HDMI_D0_N          (HDMI_D0_N)); clk_wiz_0   u_clk(.clk_in1            (clk_100M),.resetn              (1'b1),.clk_out1           (pixclk),//74.25MHz.clk_out2           (serclk),//371.25MHz.locked             (lock));endmodule

4、顶层模块:

在top中将cube_ctrl和HDMI_display实例化,代码如下:

module HDMI_display(input clk_100M,input rst_n,input [4:0]KEY_Value,output HDMI_CLK_P,output HDMI_CLK_N,output HDMI_D2_P,output HDMI_D2_N,output HDMI_D1_P,output HDMI_D1_N,output HDMI_D0_P,output HDMI_D0_N,output pixclk
);// wire pixclk;wire[7:0]   R,G,B;wire HS,VS,DE;hdmi_data_gen u_hdmi_data_gen(// .clk(clk_100M),.rst_n(rst_n),.KEY_Value(KEY_Value),.pix_clk            (pixclk),.VGA_R              (R),.VGA_G              (G),.VGA_B              (B),.VGA_HS             (HS),.VGA_VS             (VS),.VGA_DE             (DE));wire serclk;wire lock;wire[23:0]  RGB;assign RGB={R,G,B};HDMI_FPGA_ML_0 u_HDMI(.PXLCLK_I           (pixclk),.PXLCLK_5X_I        (serclk),.LOCKED_I           (lock),.RST_N              (1'b1),.VGA_HS             (HS),.VGA_VS             (VS),.VGA_DE             (DE),.VGA_RGB            (RGB),.HDMI_CLK_P         (HDMI_CLK_P),.HDMI_CLK_N         (HDMI_CLK_N),.HDMI_D2_P          (HDMI_D2_P),.HDMI_D2_N          (HDMI_D2_N),.HDMI_D1_P          (HDMI_D1_P),.HDMI_D1_N          (HDMI_D1_N),.HDMI_D0_P          (HDMI_D0_P),.HDMI_D0_N          (HDMI_D0_N)); clk_wiz_0   u_clk(.clk_in1            (clk_100M),.resetn              (1'b1),.clk_out1           (pixclk),//74.25MHz.clk_out2           (serclk),//371.25MHz.locked             (lock));endmodulemodule top(input clk,input rst_n,input [1:0]rotate_mode,//00->顺90度,01->180度,11->逆90度input [5:0]key_n,output HDMI_CLK_P,output HDMI_CLK_N,output HDMI_D2_P,output HDMI_D2_N,output HDMI_D1_P,output HDMI_D1_N,output HDMI_D0_P,output HDMI_D0_N);wire [4:0]KEY_Value;//模块实例化cube_ctrl C_C(.clk(pixclk),.rst_n(rst_n),.rotate_mode(rotate_mode),.key_n(key_n),.KEY_Value(KEY_Value));HDMI_display H_D(.clk_100M(clk),.rst_n(rst_n),.KEY_Value(KEY_Value),.HDMI_CLK_P(HDMI_CLK_P),.HDMI_CLK_N(HDMI_CLK_N),.HDMI_D2_P(HDMI_D2_P),.HDMI_D2_N(HDMI_D2_N),.HDMI_D1_P(HDMI_D1_P),.HDMI_D1_N(HDMI_D1_N),.HDMI_D0_P(HDMI_D0_P),.HDMI_D0_N(HDMI_D0_N),.pixclk(pixclk)
);
endmodule

三、约束文件

1、键盘的管脚约束

根据ZYBO的开发板手册得到其Pmod接口如下,我们使用的是JE标准接口。

根据原理图找到管脚的位置:

2、HDMI TX端的管脚约束

根据原理图找到HDMI TX端,根据管脚名称找到对应的管脚进行绑定

3、完整约束文件

set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]set_property IOSTANDARD LVCMOS33 [get_ports {key_n[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {key_n[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {key_n[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {key_n[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {key_n[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {key_n[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {rotate_mode[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rotate_mode[0]}]set_property PACKAGE_PIN K17 [get_ports clk]
set_property PACKAGE_PIN T16 [get_ports rst_n]set_property PACKAGE_PIN V12 [get_ports {key_n[5]}]
set_property PACKAGE_PIN W16 [get_ports {key_n[4]}]
set_property PACKAGE_PIN J15 [get_ports {key_n[3]}]
set_property PACKAGE_PIN V13 [get_ports {key_n[2]}]
set_property PACKAGE_PIN U17 [get_ports {key_n[1]}]
set_property PACKAGE_PIN T17 [get_ports {key_n[0]}]set_property PACKAGE_PIN P15 [get_ports {rotate_mode[1]}]
set_property PACKAGE_PIN G15 [get_ports {rotate_mode[0]}]set_property -dict {PACKAGE_PIN H17 IOSTANDARD TMDS_33} [get_ports HDMI_CLK_N]
set_property -dict {PACKAGE_PIN H16 IOSTANDARD TMDS_33} [get_ports HDMI_CLK_P]
set_property -dict {PACKAGE_PIN D20 IOSTANDARD TMDS_33} [get_ports HDMI_D0_N]
set_property -dict {PACKAGE_PIN D19 IOSTANDARD TMDS_33} [get_ports HDMI_D0_P]
set_property -dict {PACKAGE_PIN B20 IOSTANDARD TMDS_33} [get_ports HDMI_D1_N]
set_property -dict {PACKAGE_PIN C20 IOSTANDARD TMDS_33} [get_ports HDMI_D1_P]
set_property -dict {PACKAGE_PIN A20 IOSTANDARD TMDS_33} [get_ports HDMI_D2_N]
set_property -dict {PACKAGE_PIN B19 IOSTANDARD TMDS_33} [get_ports HDMI_D2_P]

四、综合与上板验证

1、综合

在vivado中进行综合、布局布线结果如下:

2、上板效果

FPGA虚拟三阶魔方(HDMI显示版)

详见视频,工程将上传至github,链接:https://github.com/lionelZhaowy/FPGA-CUBE.git

FPGA-CUBE

FPGA虚拟三阶魔方(HDMI显示版)相关推荐

  1. activiti高亮显示图片_【正点原子FPGA连载】第二十章SD卡读BMP图片HDMI显示实验领航者 ZYNQ 之嵌入式开发指南...

    1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下 ...

  2. 基于FPGA的HDMI显示(二)

    基于FPGA的720P HDMI显示 1.4.1 HDMI 硬件电路分析   本次设计采用了 IO 模拟的方式实现 HDMI 的功能.与采用专用 HDMI 芯片相比,此方案具有成本更低.效果不输于采用 ...

  3. 【正点原子FPGA连载】第四十四章MT9V034摄像头HDMI显示实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1

    1)实验平台:正点原子新起点V2开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=609758951113 2)全套实验源码+手册+视频下载地址:ht ...

  4. 虚拟魔方——使用python对普通三阶魔方进行建模

    使用python对普通三阶魔方进行建模 1 整体构想 1.1 建立虚拟魔方 1.1.1 为魔方的26个方块进行定义 1.1.2 利用图形化方式表示魔方 1.2 对魔方进行操作 1.3 实现对魔方公式的 ...

  5. FPGA - 基于FPGA的HDMI显示

    写在前面 HDMI接口很早之前就想调试了,由于没有时间,就拖到了现在,而且毕业设计也是和视频处理系统有关,就趁这个机会把这个接口调试下. 开发环境 vivado 18.3 pynq - z2 HDMI ...

  6. 基于FPGA的HDMI显示(一)

    1.1 HDMI简介 简介略,网上很多,这里也不过多描述. 1.2 基于FPGA的HDMI接口设计   HDMI输出接口在FPGA方面应用时,主要有两种方式:一种就是如图1 22所示的方式,采用Sil ...

  7. 基于FPGA的 TMDS 编码 及 HDMI 显示

    目录 引言 TMDS 编码 原理简介 TMDS编码实现 HDMI差分数据串行 实现方法 源码 HDMI显示方法 思路 实现 工程结构 源代码分享 板级调试视频 引言 最近在开发板上倒腾了一下 TMDS ...

  8. 【正点原子FPGA连载】 第三十五章双目OV5640摄像头HDMI显示实验 摘自【正点原子】DFZU2EG/4EV MPSoC 之FPGA开发指南V1.0

    1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670 3)全套实验源码+手册+视频下载地址: h ...

  9. 【正点原子FPGA连载】第五十六章 双目OV5640摄像头HDMI显示实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1

    1)实验平台:正点原子新起点V2开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=609758951113 3)全套实验源码+手册+视频下载地址:ht ...

最新文章

  1. java反射机制的调用
  2. linux jar命令找不到 -bash: jar: command not found
  3. 世界首台!我国量子计算机超越早期经典计算机
  4. NYOJ 289 苹果
  5. 函数的返回是返回给实参,然后由实参输出,返回值的作用是给输出的全部变为变量然后用.=连接好把变量存进数据库而不是输出完屏幕就拉倒了...
  6. 在 WebStorm 中误添加自定义的 HTML 属性,如何删除
  7. 宝宝头三年至关重要,不看悔掉肠子
  8. eclipse mat 分析dump文件,打开文件报错,out of memeory
  9. 二维码提升对比度文献调研(4)--Attention Guided Low-light Image Enhancement
  10. templates是什么意思_什么?噪音可以用来降温做冰箱?
  11. ViT (Vision Transformer) ---- Text Generation(文本生成器)
  12. 我今天学习的技术,明天会不会一钱不值
  13. Dubbo2.7源码分析-如何发布服务
  14. 怎样使用Google chrome播放 .swf 文件
  15. 如何避免渠道商的“养卡”和“劝弃卡”行为的发生
  16. 语法分析器(c++)
  17. 按键精灵什么是动态数组?如何使用动态数组?(新手进阶)
  18. Ubuntu上安装搜狗中文输入法
  19. 去掉数组中是数字的引号
  20. Serv-u ftpserver 删除问题

热门文章

  1. 感谢有你!所有贡献者来领礼物了
  2. JSP使用Websocket技术实现聊天功能--H5网页前端部分(二)
  3. CoordinatorLayout+AppBarLayout 提供最佳浏览体验
  4. 十九世纪的两朵乌云开始-未完
  5. IPv4之发送接口: ip_queue_xmi()
  6. [转]机器学习科普文章:“一文读懂机器学习,大数据/自然语言处理/算法全有了”
  7. 物联网在公共安全中的应用
  8. 一个bug引发的血案(大爆炸)
  9. 用python实现四位数字猜几A几B游戏代码
  10. 首篇极客解题报告意外泄出!亚军竟有神操作?