**这是本文档旧的修订版!**
NMPSM3软处理器
NMPSM3概述
在UCSC扩展学院上了第一门FPGA课后,我对这些设备为普通人提供的功能感到惊讶,我决定更深入地研究它们。我最终意识到我有足够的逻辑设计知识,可以构建自己的简单处理器。在了解了KCPSM(nanoblaze)之后,我开始构建自己的处理器,并将其称为NMPSM(Nick Mikstas可编程状态机)。我花了三遍迭代才能制作出功能全面的处理器,因此命名为NMPSM3。即使NMPSM3受到nanoblaze IO方案的启发,其内部结构也完全不同。NMPSM3是具有四个独立中断和一个复位的16位处理器。NMPSM至少需要实现四个18Kb BRAMS:一个用于寄存器,一个用于堆栈,一个用于解码器,至少一个用于程序ROM。使处理器正常工作后,我为其编写了汇编程序,并创建了一个大型项目以展示其功能。
当我第一次设计NMPSM3时,它是在Digilent Nexys 2板上实现的。Nexys 2上有Xilinx Spartan 3部件。在成功实施该项目之后,几年来我对NMPSM3一无所获。我最终在SCU上了一门课,基本上和UCSC Extension上的一门课一样。我决定通过更新项目以使其在Digilent Basys 3 FPGA板上工作来使NMPSM3振作起来。由于新的FPGA部件(Artyx 7)比Spartan 3具有更多的功能,因此我也对该项目进行了一些升级。我也写了一份详尽的报告。
NMPSM3屏幕截图
NMPSM3硬件
与处理器一起,我还基于8位Nintendo构建了其他一些模块,包括UART和图片处理单元(PPU)。一些Verilog代码很粗糙,因为在创建此项目时我正在学习Verilog。
Final_Project.v
`timescale 1ns / 1ps module Final_Project( input clk, input [15:0]sw, input btnC, input btnU, input btnD, input btnL, input btnR, input data, input RsRx, output RsTx, output RxTest, output TxTest, output [15:0]led, output [6:0]seg, output [3:0]an, output dp, output [3:0]vgaRed, output [3:0]vgaGreen, output [3:0]vgaBlue, output Hsync, output Vsync, output sclk, output ce ); //UART test ports. assign RxTest = RsRx; assign TxTest = RsTx; wire clk100MHz; wire clk50MHz; wire clk25MHz; wire t0out; wire t1out; wire ack0; wire ack1; wire ack2; wire ack3; wire sigout0; wire sigout1; wire sigout2; wire sigout3; wire ce1k; wire blink; wire read; wire write; wire vblank; wire reset; wire [15:0]id; wire [15:0]outdata; wire [7:0]hour; wire [7:0]min; wire [7:0]sec; wire [35:0]inst; wire [15:0]in_port; wire [15:0]address; wire [7:0]romdata; wire [11:0]mdout; wire [7:0]vgadata; wire [9:0]addr; wire [10:0]romaddress; wire [11:0]mdin; //UART wires. wire [7:0]uartdata; wire [11:0]txcount; wire [11:0]rxcount; //Unused VGA bits in this design. assign vgaRed[0] = 1'b0; assign vgaGreen[0] = 1'b0; assign vgaBlue[0] = 1'b0; assign vgaBlue[1] = 1'b0; //Reset signal. assign reset = btnU; //Flip-flop for interrupt 0. FF ff0(.set(t0out), .reset(ack0), .sigout(sigout0)); //Flip-flop for interrupt 1. FF ff1(.set(t1out), .reset(ack1), .sigout(sigout1)); //Flip-flop for interrupt 2. FF ff2(.set(vblank), .reset(ack2), .sigout(sigout2)); //Flip-flop for interrupt 3(not used). FF ff3(.set(1'b0), .reset(ack3), .sigout(sigout3)); //Divide by 100,000. div100k divideBy100K(.clock(clk100MHz), .ce1k(ce1k)); //Clock divider. clk25 c(.clk_in1(clk), .clk_out1(clk100MHz), .clk_out2(clk50MHz), .clk_out3(clk25MHz)); //NMPSM3 soft processor. NMPSM3 nmpsm3(.clk(clk100MHz), .reset(reset), .IRQ0(sigout0), .IRQ1(sigout1), .IRQ2(sigout2), .IRQ3(sigout3), .INSTRUCTION(inst), .IN_PORT(in_port), .READ_STROBE(read), .WRITE_STROBE(write), .IRQ_ACK0(ack0), .IRQ_ACK1(ack1), .IRQ_ACK2(ack2), .IRQ_ACK3(ack3), .ADDRESS(address), .OUT_PORT(outdata), .PORT_ID(id)); //Program ROM for NMPSM3. Program_ROM prgROM(.clka(clk100MHz), .addra(address[9:0]), .douta(inst)); //Lookup ROM Lookup_ROM lookuprom(.clka(clk100MHz), .addra(romaddress), .douta(romdata)); //UART uart uart1(.clk(clk100MHz), .reset(reset), .id(id), .din(outdata), .write(write), .rx(RsRx), .tx(RsTx), .dout(uartdata), .rxcount(rxcount), .txcount(txcount)); //LED output controller. ledio LEDIO(.clk(clk100MHz), .reset(reset), .write(write), .id(id), .din(outdata), .ledsout(led[7:0])); //LED output controller 2. LEDIO2 ledio2(.clk(clk100MHz), .reset(reset), .write(write), .id(id), .din(outdata), .ledsout(led[15:8])); //Seven segment controller. seg7io seg7control(.clk(clk100MHz), .ce1k(ce1k), .write(write), .reset(reset), .id(id), .din(outdata), .segselect(an), .segs({dp,seg})); //Timer 0. timer0 time0(.clk(clk100MHz), .cein(ce1k), .write(write), .reset(reset), .id(id), .din(outdata), .dout(t0out)); //Timer 1. timer1 time1(.clk(clk100MHz), .cein(ce1k), .write(write), .reset(reset), .id(id), .din(outdata), .dout(t1out)); //ROM controller for lookup ROM. ROMcontroller ROMcontrol(.clk(clk100MHz), .id(id), .ain(outdata), .aout(romaddress)); //Processor input data MUX. dataMUX datamux(.read(read), .blink(blink), .id(id), .i2cdata(16'd0), .i2cstatus(16'd0), .xpos(16'd0), .ypos(16'd0), .uartdata({8'h00,uartdata}), .txcount(txcount), .rxcount(rxcount), .romdata(romdata), .switches(sw), .sec(sec), .min(min), .hour(hour), .micdata({btnD, 3'h0, mdout}), .dout(in_port)); //Clock control. ClockControl clockcontrol(.clock(clk100MHz), .ce_1KHz(ce1k), .button({btnD, btnL, btnC, btnR}), .blink(blink), .hour(hour), .min(min), .sec(sec)); //Picture processing unit. VGA ppu(.clk25MHz(clk25MHz), .clk(clk100MHz), .write(write), .id(id), .data(outdata[7:0]), .vblank(vblank), .vsync(Vsync), .hsync(Hsync), .vga({vgaBlue[3:2], vgaGreen[3:1], vgaRed[3:1]})); //Microphone control. MControl mc(.clk(clk100MHz), .reset(reset), .serialdata(data), .nenable(ce), .sclk(sclk), .micdata(mdout)); endmodule
NMPSM3.v