在FPGA开发板上玩《超级玛丽》之笔记 -(2)重构2A03CPU
本人所写的博客都为开发之中遇到问题记录的随笔,主要是给自己积累些问题。免日后无印象,如有不当之处敬请指正(欢迎进扣群 24849632 探讨问题);
要在不改变NES文件的情况下运行游戏程序,那么需要有一颗可以运行此机器码的CPU,因此我打算从开始重构一颗2A03CPU开始。经过这两天的工作,现在CPU的框架已经完成。
这个版本并没有按8位机的规范进行时序流程的设计,16位地址的计算直接使用两个加法单元,期待在一个时钟周期内,便将6502的绝对地址间接寻址功能完成了地址进行计算、内存取数、间接计算、甚至数据回存都完成。但因为时序逻辑比较混乱,QUARTS II 在生成网表时将所有的逻辑门都优化成了0,因此为了更快的解决问题,因此这一版本的架构直接做废。
第二版本重新对CPU的架构进行了优化,完全按8位机的架构进行设计,以下便将完成框架图中的各个组件,并完成子模块的仿真及设计。
编写PC及最简控制器
stack.vhdl
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL; entity stack is generic (SIZE:INTEGER := 128); port(wr : IN std_logic; cs : IN std_logic; clk : IN std_logic; reset : IN std_logic; addr : INOUT std_logic_vector(15 downto 0) );
end stack; architecture arch_stack of stack is
type stack_ARRAY is array (0 to SIZE-1) of std_logic_vector (15 downto 0);
signal stack_body : stack_ARRAY;
signal stack_postion : integer range 0 to 127;
begin process(clk,reset) begin if(reset='1') then stack_postion <= 0; elsif(rising_edge(clk)) then if(cs='1') then if(wr='1') then --pop addr <= stack_body(stack_postion); stack_postion <= stack_postion-1; else stack_body(stack_postion) <= addr; stack_postion <= stack_postion+1; end if; end if; end if; end process;
end arch_stack; -- configuration config_stack of stack is
-- for arch_stack
-- end for;
-- end configuration;
rom.vhdl
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE WORK.PRJCONFIG.ALL;entity rom is generic (SIZE:INTEGER := 256); port(clk : IN std_logic; wr : IN std_logic; addr : IN std_logic_vector(15 downto 0); data : IN std_logic_vector(7 downto 0); code : OUT std_logic_vector(7 downto 0) );
end rom; architecture arch_rom of rom is
type rom_ARRAY is array (SIZE-1 downto 0) of std_logic_vector (7 downto 0);
signal rom_body : rom_ARRAY;
begin process(clk) variable addr_temp: BYTE; begin if(rising_edge(clk)) then if(addr(15)='1') then -- address limit at 8000H ~ FFFFH addr_temp := conv_integer(addr); if(wr='1') then rom_body(addr_temp) <= data; else code <= rom_body(addr_temp); end if; end if; end if; end process;
end arch_rom; -- configuration config_rom of rom is
-- for arch_rom
-- end for;
-- end configuration;
pc.vhdl
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
-- USE IEEE.NUMERIC_STD.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE WORK.PRJCONFIG.ALL;entity pc is port (-- input from global clk : in std_logic; -- input form nesupdatareset : in std_logic; -- input form controller ent : in std_logic; load : in std_logic; model : in std_logic_vector(1 downto 0); preset : in std_logic_vector(15 downto 0); -- io to statck saddr : inout std_logic_vector(15 downto 0); -- output to rom pcout : out std_logic_vector(15 downto 0) );
end pc; architecture arch_pc of pc is
signal current_pc: WORD := 0;
beginprocess(clk,reset,load,model) begin -- clock process if(reset='1') then -- 【复位信号】为高时清除PC值,回程序起始位置 current_pc <= 0; elsif(rising_edge(clk)) then if(model(1)='1') then -- 【栈地址】保存与恢复 if(load='1') then -- from stack to pc current_pc <= CONV_INTEGER(saddr); else -- from pc to stack saddr <= CONV_STD_LOGIC_VECTOR(current_pc,16); end if; elsif(model(0)='1') then if(load='1') then -- 从地址预设线中加载地址数据 current_pc <= CONV_INTEGER(preset); elsif(ent='1') then -- 指向下一指令地址 current_pc <= current_pc+1; end if; saddr <= (others=>'Z'); end if; pcout <= CONV_STD_LOGIC_VECTOR(current_pc,16); end if; end process;
end arch_pc;
nesupdata.vhdl
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE WORK.PRJCONFIG.ALL;entity nesupdata is port(-- from global clk : IN std_logic;reset_n : IN std_logic;-- avalon jock avalon_wr : IN std_logic; avalon_addr: IN std_logic_vector(2 downto 0); avalon_data: IN std_logic_vector(24 downto 0); -- output to rom rom_wr : OUT std_logic; rom_addr : OUT std_logic_vector(15 downto 0); rom_data : OUT std_logic_vector(7 downto 0); -- output to pc sys_reset : OUT std_logic; -- output to control ctr_pause : OUT std_logic );
end nesupdata; architecture arch_nesupdata of nesupdata is
begin process(clk,reset_n) begin if(reset_n='0') then sys_reset <= '1'; ctr_pause <= '1'; elsif(rising_edge(clk)) then sys_reset <= '0'; if(avalon_wr='0') then case avalon_addr is when "000" => -- nes 数据下载或停止命令 if(avalon_data(0)='1') then rom_wr <= '1'; ctr_pause <= '1'; sys_reset <= '1'; else rom_wr <= '0'; end if; when "001" => -- 下载NES调色板数据 rom_addr <= avalon_data(23 downto 8); rom_data <= avalon_data(7 downto 0); when "010" => -- 下载NES游戏数据 rom_addr <= avalon_data(23 downto 8); rom_data <= avalon_data(7 downto 0); when "011" => -- NES游戏开始 rom_wr <= '0'; ctr_pause <= '0'; sys_reset <= '0'; when others => null; end case; end if; end if; end process;
end arch_nesupdata;
controller.vhdl
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
-- USE IEEE.NUMERIC_STD.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE WORK.PRJCONFIG.ALL;entity controller is port (-- input from global clk : in std_logic; -- nesupdate to controller reset : in std_logic; pause : in std_logic; -- controller to pc ent : out std_logic; load : out std_logic; abs_addr : out std_logic_vector(15 downto 0); -- rom to controller rom_code : in std_logic_vector(7 downto 0); -- memory & controller op_cmd : out std_logic_vector(15 downto 0); mem_addr : out std_logic_vector(15 downto 0); mem_data : inout std_logic_vector(7 downto 0); -- register status : inout std_logic_vector(7 downto 0) );
end controller; architecture arch_controller of controller is
signal cmd_type: INDTYPE;
signal acc_temp,x_temp,y_temp: std_logic_vector(7 downto 0);
signal future_state, current_state: PRCSTATU;
beginprocess(clk,reset,pause) begin if(reset='1') then future_state <= PRCSTATU_READY;elsif(rising_edge(clk)) thenif(pause='1') then -- op_cmd <= "0001000001000001"; op_cmd <= cmdCreate(OPCMD_FUN_ADD, -- 算式单元功能选择 OPCMD_ITEM_DISENB, -- 算式单元使能 OPCMD_ITEM_DISENB, -- Y寄存器片选 OPCMD_ITEM_DISENB, -- Y寄存器写使能 OPCMD_ITEM_DISENB, -- X寄存器片选 OPCMD_ITEM_DISENB, -- X寄存器写使能 OPCMD_ITEM_ENB, -- ACC寄存器片选 OPCMD_ITEM_DISENB, -- ACC寄存器写使能 OPCMD_ITEM_DISENB, -- RAM存储器写使能 OPCMD_ITEM_DISENB, -- ZPG存储器写使能 OPCMD_ITEM_DISENB, -- PPU存储器写使能 OPCMD_ITEM_DISENB, -- STACK存储器写使能 OPCMD_ITEM_ENB -- PC寄存器写使能 ); end if; current_state <= future_state; end if;end process; process(current_state,rom_code) -- rom chip select & postion move signal -- procedure romshift(rd: in std_logic; mv: in std_logic) is -- begin -- pc_cs <= rd; -- pc_ent <= mv; -- end romshift; begin -- 状态机指令解析 case current_state is when PRCSTATU_READY => -- 取指令操作码 case rom_code is when X"6D" => -- ADC abs cmd_type <= INDT_ABS; acc_temp <= mem_data; mem_data <= not(status); -- when 16#E8# => res := 1; -- INX -- when 16#C8# => res := 1; -- INY -- when 16#CA# => res := 1; -- DEX -- when 16#88# => res := 1; -- DEY -- when 16#0A# => res := 1; -- ASL -- when 16#4A# => res := 1; -- LSR -- when 16#2A# => res := 1; -- ROL -- when 16#6A# => res := 1; -- ROR -- when 16#00# => res := 1; -- BRK-- when 16#40# => res := 1; -- RTI -- when 16#60# => res := 1; -- RTS -- when 16#18# => res := 1; -- CLC -- when 16#D8# => res := 1; -- CLD -- when 16#58# => res := 1; -- CLI -- when 16#B8# => res := 1; -- CLV -- when 16#38# => res := 1; -- SEC -- when 16#F8# => res := 1; -- SED -- when 16#78# => res := 1; -- SEI -- when 16#AA# => res := 1; -- TAX -- when 16#A8# => res := 1; -- TAY -- when 16#BA# => res := 1; -- TSX -- when 16#8A# => res := 1; -- TXA -- when 16#9A# => res := 1; -- TXS -- when 16#98# => res := 1; -- TYA -- when 16#48# => res := 1; -- PHA -- when 16#08# => res := 1; -- PHP -- when 16#68# => res := 1; -- PLA -- when 16#28# => res := 1; -- PLP -- when 16#EA# => res := 1; -- NOP -- when 16#6D# => res := 3; -- ADC abs -- when 16#7D# => res := 3; -- ADC abs,x -- when 16#79# => res := 3; -- ADC abs,y -- when 16#EE# => res := 3; -- INC abs -- when 16#FE# => res := 3; -- INC abs,x -- when 16#ED# => res := 3; -- SBC abs -- when 16#FD# => res := 3; -- SBC abs,x -- when 16#F9# => res := 3; -- SBC abs,y -- when 16#CE# => res := 3; -- DEC abs -- when 16#DE# => res := 3; -- DEC abs,x -- when 16#2D# => res := 3; -- AND abs -- when 16#3D# => res := 3; -- AND abs,x-- when 16#39# => res := 3; -- AND abs,y-- when 16#4D# => res := 3; -- EOR abs-- when 16#5D# => res := 3; -- EOR abs,x -- when 16#59# => res := 3; -- EOR abs,y -- when 16#0D# => res := 3; -- ORA abs -- when 16#11# => res := 3; -- ORA (abs),y -- when 16#1D# => res := 3; -- ORA abs,x -- when 16#19# => res := 3; -- ORA abs,y -- when 16#2C# => res := 3; -- BIT abs -- when 16#0E# => res := 3; -- ASL abs -- when 16#1E# => res := 3; -- ASL abS,x -- when 16#4E# => res := 3; -- LSR abs -- when 16#5E# => res := 3; -- LSR abs,x -- when 16#2E# => res := 3; -- ROL abs-- when 16#3E# => res := 3; -- ROL abs,x-- when 16#6E# => res := 3; -- ROR abs-- when 16#7E# => res := 3; -- ROR abs,x-- when 16#4C# => res := 3; -- JMP abs-- when 16#6C# => res := 3; -- JMP (abs)-- when 16#20# => res := 3; -- JSR oper -- when 16#CD# => res := 3; -- CMP abs -- when 16#DD# => res := 3; -- CMP abs,x -- when 16#D9# => res := 3; -- CMP abs,y -- when 16#EC# => res := 3; -- CPX abs -- when 16#CC# => res := 3; -- CPY abs -- when 16#AD# => res := 3; -- LDA abs -- when 16#BD# => res := 3; -- LDA abs,x -- when 16#B9# => res := 3; -- LDA abs,y -- when 16#AE# => res := 3; -- LDX abs -- when 16#BE# => res := 3; -- LDX abs,y -- when 16#AC# => res := 3; -- LDY abs -- when 16#BC# => res := 3; -- LDY abs,X -- when 16#8D# => res := 3; -- STA abs-- when 16#9D# => res := 3; -- STA abs,x-- when 16#99# => res := 3; -- STA abs,y-- when 16#8E# => res := 3; -- STX abs-- when 16#8C# => res := 3; -- STY abswhen others => null; end case; when others => NULL; end case; end process;
end arch_controller;
简单的编写了CPU架构的ROM读取读取及更新部份,编译后依然得到的逻辑数为0
这就有点儿郁闷了,这个问题是因为什么问题造成的呢?
难不成问题是输入输出引脚间没有对应关系吗?我这是一个CPU,它虽然有输出引脚,但是却是键盘接口与显示器接口,那下面我就先随便的添加一个简单的外部IO试试看是不是因为这个原因吧!
在FPGA开发板上玩《超级玛丽》之笔记 -(2)重构2A03CPU相关推荐
- fpga驱动rgb液晶屏_正点原子开拓者FPGA开发板资料连载第五十四章基于的数字识别实验...
1)实验平台:正点原子开拓者FPGA 开发板 2)摘自<开拓者FPGA开发指南>关注官方微信号公众号,获取更多资料:正点原子 3)全套实验源码+手册+视频下载地址:http://www.o ...
- 在S3C6410开发板上的LED驱动程序
这两天写了个LED驱动程序,网上也看了好多的帖子. 开始思路很清晰了,就是先看电路图,发现LED灯是接在GPM端口上的, 然后看S3C6410数据手册,先向GPMCON口写命令字,让GPM0-5设置为 ...
- 共阳数码管段码表_正点原子开拓者FPGA开发板资料连载第十一章 静态数码管显示实验...
1)实验平台:正点原子开拓者FPGA 开发板 2)摘自<开拓者FPGA开发指南>关注官方微信号公众号,获取更多资料:正点原子 3)全套实验源码+手册+视频下载地址:http://www.o ...
- 国产荔枝糖FPGA开发板实现FM发射
之前在ZEDBOARD上实现了FM发射,移植到荔枝糖FPGA开发板上,运行异常,抓波形看,波形紊乱,由于最高时钟为450M,估计是荔枝糖FPGA开发板跑不了这么高,那就降频吧,降到18M果然可以发射了 ...
- 基于FPGA开发板使用Verilog设计PWM呼吸灯实验
基于FPGA开发板使用Verilog设计PWM呼吸灯实验 1,实验原理 2,实验模块设计 2.1 RTL设计,呼吸灯模块设计 2.2,测试数据,下载到FPGA开发板板级的数据 2.3,两个模块综合的n ...
- VHDL编写多功能数字钟,spartan3 FPGA开发板硬件实现-学习笔记
VHDL编写多功能数字钟,spartan3 FPGA开发板硬件实现-学习笔记 多功能数字钟硬件测试视频: https://www.bilibili.com/video/av62501230 1.数字钟 ...
- html抽奖源码_开源FPGA开发板OpenICE 介绍及抽奖
首先呢,先强调一遍,我做板子不是为了挣钱,因为国内目前的形式比较严峻,只是为了体验一下开源的工具和环境,也为了后人能对FPGA有个新的认识,所以不会触碰到任何人的蛋糕. 本来今天不准备发文了,还是熬夜 ...
- 开源RISC-V 项目Freedom在Arty-7-100T开发板上的实现
开源RISC-V 项目Freedom在Arty-7-100T开发板上的实现 1.获取Freedom项目源码 Freedom项目开源的地址为https://github.com/sifive/freed ...
- 开源FPGA开发板-OpenICE 介绍及抽奖
首先呢,先强调一遍,我做板子不是为了挣钱,因为国内目前的形式比较严峻,只是为了体验一下开源的工具和环境,也为了后人能对FPGA有个新的认识,所以不会触碰到任何人的蛋糕. 本来今天不准备发文了,还是熬夜 ...
- 【小月电子】ALTERA FPGA开发板系统学习教程-LESSON12 IPCORE核之FIFO详细教程
ALTERA FPGA IPCORE核之FIFO详细教程 若要观看该博客配套的视频教程,可点击此链接 一. FIFO简介 FIFO: 是英文first in first out的缩写,即先进先出,指的 ...
最新文章
- go 获得 mysql 实际运行 SQL,Golang实践录:一个数据库迁移的代码记录
- 打印二叉搜索树的叶子结点_求孩子兄弟树叶子节点数目
- Water Balance CodeForces - 1300E
- 电子计算机职业40201,天津滨海中等专业学校
- 云服务器主体信息可以变更吗,云服务器备案号是什么?备案号存在能否更换云服务器?...
- qtreewidgetitem 文字内存太长换行_table文字溢出显示省略号问题
- 如何使frame能居中显示
- 翻译Java虚拟机的结构
- FPGA 独立按键消抖
- 基于MT5的沪深股票回测二 导入历史数据
- Spring Boot 3.x特性-JSON(gson,jackson,json-b,fastjson)
- D. Pythagorean Triples (math、暴力)
- ffmpeg学习:滤镜(实现视频缩放,裁剪,水印等) -
- MaxEnt软件的使用
- 关于Java中Match类的appendReplacement()方法的一个坑{ character to be escaped }
- 粒子群算法python(含例程代码与详解)
- 和鲸社区的滴滴出行数据分析项目
- 交换机虚拟化和堆叠的区别_交换机级联与堆叠有何区别?(内含堆叠方法)
- 2021年电工(中级)考试题库及电工(中级)最新解析
- 重庆主城跑步地图|总有一条跑道适合你
热门文章
- TCR历史论文多久能发表?
- Unity 2D横版闯关游戏 (JUNGLE RULES)
- Data Management Platform 数据管理平台全接触
- springmvc防xss脚本注入攻击,springmvc过滤html和js标签,html和js标签转义
- 【网络安全】入侵防御系统
- 人人商城互动直播(与通信服务器连接失败)
- 中国移动通信互联网短信网关接口协议 (China Mobile Peer to Peer, CMPP) (V2.0)
- pycharm一些常用的搜索快捷键
- MATLAB做三维图时值为0的点不画出来
- 小尺寸2.4G SMD贴片天线方案 CA-C03 CrossAir贴片天线