123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913 |
- `timescale 1ns / 1ps
- //////////////////////////////////////////////////////////////////////////////////
- // Company:
- // Engineer:
- //
- // Create Date: 23:14:37 10/13/2011
- // Design Name:
- // Module Name: cx4
- // Project Name:
- // Target Devices:
- // Tool versions:
- // Description:
- //
- // Dependencies:
- //
- // Revision:
- // Revision 0.01 - File Created
- // Additional Comments:
- //
- //////////////////////////////////////////////////////////////////////////////////
- module cx4(
- input [7:0] DI,
- output [7:0] DO,
- input [12:0] ADDR,
- input CS,
- input SNES_VECT_EN,
- input nRD,
- input nWR,
- input CLK,
- input [23:0] DATROM_DI,
- input DATROM_WE,
- input [9:0] DATROM_ADDR,
- input [7:0] BUS_DI,
- output [23:0] BUS_ADDR,
- output BUS_RRQ,
- input BUS_RDY,
- output cx4_active
- );
- reg [2:0] cx4_busy;
- parameter BUSY_CACHE = 2'b00;
- parameter BUSY_DMA = 2'b01;
- parameter BUSY_CPU = 2'b10;
- wire datram_enable = CS & (ADDR[11:0] < 12'hc00);
- wire mmio_enable = CS & (ADDR[12:5] == 8'b11111010) & (ADDR[4:0] < 5'b10011);
- wire status_enable = CS & (ADDR[12:5] == 8'b11111010) & (ADDR[4:0] >= 5'b10011);
- wire vector_enable = (CS & (ADDR[12:5] == 8'b11111011)) | (cx4_active & SNES_VECT_EN);
- wire gpr_enable = CS & (&(ADDR[12:7]) && ADDR[5:4] != 2'b11);
- wire pgmrom_enable = CS & (ADDR[12:5] == 8'b11110000);
- wire [7:0] DATRAM_DO;
- reg [7:0] MMIO_DOr;
- wire [7:0] MMIO_DO;
- wire [7:0] STATUS_DO;
- wire [7:0] VECTOR_DO;
- wire [7:0] GPR_DO;
- assign DO = datram_enable ? DATRAM_DO
- : mmio_enable ? MMIO_DO
- : status_enable ? STATUS_DO
- : vector_enable ? VECTOR_DO
- : gpr_enable ? GPR_DO
- : 8'h00;
- /* 0x1f40 - 0x1f52: MMIO
- SNES: 8 bits / CX4: various */
- reg [23:0] cx4_mmio_dmasrc;
- reg [15:0] cx4_mmio_dmalen;
- reg [23:0] cx4_mmio_dmatgt;
- reg cx4_mmio_cachepage;
- reg [23:0] cx4_mmio_pgmoff;
- reg [1:0] cx4_mmio_savepage;
- reg [14:0] cx4_mmio_pgmpage;
- reg [7:0] cx4_mmio_pc;
- reg [7:0] cx4_mmio_r1f50;
- reg cx4_mmio_r1f51;
- reg cx4_mmio_r1f52;
- /* 0x1f53 - 0x1f5f: status register */
- assign cx4_active = |cx4_busy;
- /* 0x1f60 - 0x1f7f: reset vectors */
- reg [7:0] vector [31:0];
- /* 0x1f80 - 0x1faf (0x1fc0 - 0x1fef): general purpose register file
- SNES: 8 bits / CX4: 24 bits */
- reg [7:0] gpr [47:0];
- wire [47:0] cpu_mul_result;
- reg [14:0] cx4_mmio_pagemem[1:0];
- reg [23:0] const [15:0];
- reg [14:0] cachetag [1:0];
- reg [1:0] cachevalid;
- reg [14:0] cache_pgmpage;
- reg [14:0] cpu_cache_pgmpage;
- reg cache_cachepage;
- reg cpu_cache_cachepage;
- reg cpu_cache_done;
- reg [7:0] cpu_pc_stack [7:0];
- reg [7:0] cpu_page_stack;
- initial begin
- cache_pgmpage = 15'b0;
- cpu_cache_pgmpage = 15'b0;
- cache_cachepage = 1'b0;
- cpu_cache_cachepage = 1'b0;
- cpu_cache_done = 1'b0;
- cachetag[0] = 14'h0000;
- cachetag[1] = 14'h0000;
- cachevalid = 2'b00;
- cx4_busy = 3'b000;
- cx4_mmio_pgmoff = 24'h000000;
- cx4_mmio_pgmpage = 15'h0000;
- cx4_mmio_dmasrc = 24'h000000;
- cx4_mmio_dmalen = 16'h0000;
- cx4_mmio_dmatgt = 24'h000000;
- cx4_mmio_savepage = 2'b00;
- const[0] = 24'h000000;
- const[1] = 24'hffffff;
- const[2] = 24'h00ff00;
- const[3] = 24'hff0000;
- const[4] = 24'h00ffff;
- const[5] = 24'hffff00;
- const[6] = 24'h800000;
- const[7] = 24'h7fffff;
- const[8] = 24'h008000;
- const[9] = 24'h007fff;
- const[10] = 24'hff7fff;
- const[11] = 24'hffff7f;
- const[12] = 24'h010000;
- const[13] = 24'hfeffff;
- const[14] = 24'h000100;
- const[15] = 24'h00feff;
- cpu_pc_stack[0] = 8'b0;
- cpu_pc_stack[1] = 8'b0;
- cpu_pc_stack[2] = 8'b0;
- cpu_pc_stack[3] = 8'b0;
- cpu_pc_stack[4] = 8'b0;
- cpu_pc_stack[5] = 8'b0;
- cpu_pc_stack[6] = 8'b0;
- cpu_pc_stack[7] = 8'b0;
- cpu_page_stack = 8'b0;
- end
- assign MMIO_DO = MMIO_DOr;
- assign VECTOR_DO = vector [ADDR[4:0]];
- assign GPR_DO = gpr [ADDR[5:0]];
- assign STATUS_DO = {1'b0, cx4_active, 4'b0000, ~cx4_active, 1'b0};
- reg [7:0] DIr;
- always @(posedge CLK) DIr <= DI;
- reg [4:0] datram_enable_sreg;
- initial datram_enable_sreg = 5'b11111;
- always @(posedge CLK) datram_enable_sreg <= {datram_enable_sreg[3:0], datram_enable};
- reg [5:0] nWR_sreg;
- always @(posedge CLK) nWR_sreg <= {nWR_sreg[4:0], nWR};
- wire WR_EN = (nWR_sreg[5:0] == 6'b000001);
- wire DATRAM_WR_EN = datram_enable & WR_EN;
- wire MMIO_WR_EN = mmio_enable & WR_EN;
- wire VECTOR_WR_EN = vector_enable & WR_EN;
- wire GPR_WR_EN = gpr_enable & WR_EN;
- reg [23:0] cpu_idb; // tmp register for reg file read
- /* Need to cache when:
- 1f48 is written
- AND (selected cache page is invalid
- OR selected cache page does not contain requested page already)
- */
- reg CACHE_TRIG_ENr;
- reg CACHE_TRIG_EN2r;
- reg cpu_cache_en;
- initial begin
- CACHE_TRIG_ENr = 1'b0;
- CACHE_TRIG_EN2r = 1'b0;
- cpu_cache_en = 1'b0;
- end
- always @(posedge CLK) CACHE_TRIG_EN2r <= CACHE_TRIG_ENr;
- wire CACHE_TRIG_EN = CACHE_TRIG_EN2r;
- reg DMA_TRIG_ENr;
- initial DMA_TRIG_ENr = 1'b0;
- wire DMA_TRIG_EN = DMA_TRIG_ENr;
- reg CACHE_BUS_RRQr;
- reg DMA_BUS_RRQr;
- reg cpu_bus_rq;
- initial begin
- CACHE_BUS_RRQr = 1'b0;
- DMA_BUS_RRQr = 1'b0;
- cpu_bus_rq = 1'b0;
- end
- assign BUS_RRQ = CACHE_BUS_RRQr | DMA_BUS_RRQr | cpu_bus_rq;
- reg cpu_page;
- reg [14:0] cpu_p;
- reg [7:0] cpu_pc;
- reg [23:0] cpu_a;
- reg fl_n;
- reg fl_z;
- reg fl_c;
- reg cpu_go_en_r;
- initial cpu_go_en_r = 1'b0;
- initial begin
- cx4_mmio_r1f50 = 8'h33;
- cx4_mmio_r1f51 = 1'b0;
- cx4_mmio_r1f52 = 1'b1;
- end
- always @(posedge CLK) begin
- case (ADDR[4:0])
- 5'h00: MMIO_DOr <= cx4_mmio_dmasrc[7:0]; // 1f40
- 5'h01: MMIO_DOr <= cx4_mmio_dmasrc[15:8]; // 1f41
- 5'h02: MMIO_DOr <= cx4_mmio_dmasrc[23:16]; // 1f42
- 5'h03: MMIO_DOr <= cx4_mmio_dmalen[7:0]; // 1f43
- 5'h04: MMIO_DOr <= cx4_mmio_dmalen[15:8]; // 1f44
- 5'h05: MMIO_DOr <= cx4_mmio_dmatgt[7:0]; // 1f45
- 5'h06: MMIO_DOr <= cx4_mmio_dmatgt[15:8]; // 1f46
- 5'h07: MMIO_DOr <= cx4_mmio_dmatgt[23:16]; // 1f47
- 5'h08: MMIO_DOr <= {7'b0, cx4_mmio_cachepage};
- 5'h09: MMIO_DOr <= cx4_mmio_pgmoff[7:0]; // 1f49
- 5'h0a: MMIO_DOr <= cx4_mmio_pgmoff[15:8]; // 1f4a
- 5'h0b: MMIO_DOr <= cx4_mmio_pgmoff[23:16]; // 1f4b
- 5'h0c: MMIO_DOr <= {6'b0, cx4_mmio_savepage}; // 1f4c
- 5'h0d: MMIO_DOr <= cx4_mmio_pgmpage[7:0]; // 1f4d
- 5'h0e: MMIO_DOr <= {1'b0, cx4_mmio_pgmpage[14:8]}; // 1f4e
- 5'h0f: MMIO_DOr <= cx4_mmio_pc; // 1f4f
- 5'h10: MMIO_DOr <= cx4_mmio_r1f50; // 1f50
- 5'h11: MMIO_DOr <= {7'b0, cx4_mmio_r1f51}; // 1f51
- 5'h12: MMIO_DOr <= {7'b0, cx4_mmio_r1f52}; // 1f52
- default: MMIO_DOr <= 8'hff;
- endcase
- end
- always @(posedge CLK) begin
- if(MMIO_WR_EN) begin
- case(ADDR[4:0])
- 5'h00: cx4_mmio_dmasrc[7:0] <= DIr; // 1f40
- 5'h01: cx4_mmio_dmasrc[15:8] <= DIr; // 1f41
- 5'h02: cx4_mmio_dmasrc[23:16] <= DIr; // 1f42
- 5'h03: cx4_mmio_dmalen[7:0] <= DIr; // 1f43
- 5'h04: cx4_mmio_dmalen[15:8] <= DIr; // 1f44
- 5'h05: cx4_mmio_dmatgt[7:0] <= DIr; // 1f45
- 5'h06: cx4_mmio_dmatgt[15:8] <= DIr; // 1f46
- 5'h07: begin
- cx4_mmio_dmatgt[23:16] <= DIr; // 1f47
- DMA_TRIG_ENr <= 1'b1;
- end
- 5'h08: begin
- cx4_mmio_cachepage <= DIr[0]; // 1f48
- CACHE_TRIG_ENr <= 1'b1;
- end
- 5'h09: cx4_mmio_pgmoff[7:0] <= DIr; // 1f49
- 5'h0a: cx4_mmio_pgmoff[15:8] <= DIr; // 1f4a
- 5'h0b: cx4_mmio_pgmoff[23:16] <= DIr; // 1f4b
- 5'h0c: begin
- cx4_mmio_savepage <= DIr[1:0];
- if(DIr[0]) cx4_mmio_pagemem[0] <= cx4_mmio_pgmpage;
- if(DIr[1]) cx4_mmio_pagemem[1] <= cx4_mmio_pgmpage;
- end
- 5'h0d: cx4_mmio_pgmpage[7:0] <= DIr; // 1f4d
- 5'h0e: cx4_mmio_pgmpage[14:8] <= DIr[6:0]; // 1f4e
- 5'h0f: begin
- cx4_mmio_pc <= DIr; // 1f4f
- if(cx4_mmio_savepage[0]
- && cx4_mmio_pagemem[0] == cx4_mmio_pgmpage)
- cx4_mmio_cachepage <= 1'b0;
- else if(cx4_mmio_savepage[1]
- && cx4_mmio_pagemem[1] == cx4_mmio_pgmpage)
- cx4_mmio_cachepage <= 1'b1;
- cpu_go_en_r <= 1'b1;
- end
- 5'h10: cx4_mmio_r1f50 <= DIr & 8'h77; // 1f50
- 5'h11: cx4_mmio_r1f51 <= DIr[0]; // 1f51
- 5'h12: cx4_mmio_r1f52 <= DIr[0]; // 1f52
- endcase
- end else begin
- CACHE_TRIG_ENr <= 1'b0;
- DMA_TRIG_ENr <= 1'b0;
- cpu_go_en_r <= 1'b0;
- end
- end
-
- always @(posedge CLK) begin
- if(VECTOR_WR_EN) vector[ADDR[4:0]] <= DIr;
- end
- reg [4:0] CACHE_ST;
- parameter ST_CACHE_IDLE = 5'b00001;
- parameter ST_CACHE_START = 5'b00010;
- parameter ST_CACHE_WAIT = 5'b00100;
- parameter ST_CACHE_ADDR = 5'b01000;
- parameter ST_CACHE_END = 5'b10000;
- initial CACHE_ST = ST_CACHE_IDLE;
- reg [4:0] DMA_ST;
- parameter ST_DMA_IDLE = 5'b00001;
- parameter ST_DMA_START = 5'b00010;
- parameter ST_DMA_WAIT = 5'b00100;
- parameter ST_DMA_ADDR = 5'b01000;
- parameter ST_DMA_END = 5'b10000;
- initial DMA_ST = ST_DMA_IDLE;
- reg [23:0] CACHE_SRC_ADDRr;
- wire [22:0] MAPPED_CACHE_SRC_ADDR = {CACHE_SRC_ADDRr[23:16],CACHE_SRC_ADDRr[14:0]};
- reg [23:0] DMA_SRC_ADDRr;
- wire [22:0] MAPPED_DMA_SRC_ADDR = {DMA_SRC_ADDRr[23:16],DMA_SRC_ADDRr[14:0]};
- wire [22:0] MAPPED_CPU_BUS_ADDR;
- assign BUS_ADDR = cx4_busy[BUSY_CACHE] ? MAPPED_CACHE_SRC_ADDR
- : cx4_busy[BUSY_DMA] ? MAPPED_DMA_SRC_ADDR
- : MAPPED_CPU_BUS_ADDR;
- reg cx4_pgmrom_we;
- initial cx4_pgmrom_we = 1'b0;
- reg [9:0] cx4_pgmrom_addr;
- reg [19:0] cache_count;
- initial cache_count = 20'b0;
- always @(posedge CLK) begin
- case(CACHE_ST)
- ST_CACHE_IDLE: begin
- if(CACHE_TRIG_EN
- & (~cachevalid[cx4_mmio_cachepage]
- | |(cachetag[cx4_mmio_cachepage] ^ cx4_mmio_pgmpage))) begin
- CACHE_ST <= ST_CACHE_START;
- cache_pgmpage <= cx4_mmio_pgmpage;
- cache_cachepage <= cx4_mmio_cachepage;
- cx4_busy[BUSY_CACHE] <= 1'b1;
- end else if(cpu_cache_en
- & (~cachevalid[~cpu_page]
- | |(cachetag[~cpu_page] ^ cpu_p))) begin
- CACHE_ST <= ST_CACHE_START;
- cache_pgmpage <= cpu_p;
- cache_cachepage <= ~cpu_page;
- cx4_busy[BUSY_CACHE] <= 1'b1;
- end
- else CACHE_ST <= ST_CACHE_IDLE;
- end
- ST_CACHE_START: begin
- cx4_busy[BUSY_CACHE] <= 1'b1;
- CACHE_SRC_ADDRr <= cx4_mmio_pgmoff + {cache_pgmpage, 9'b0};
- cx4_pgmrom_addr <= {cache_cachepage, 9'b0};
- CACHE_ST <= ST_CACHE_WAIT;
- cache_count <= 10'b0;
- CACHE_BUS_RRQr <= 1'b1;
- end
- ST_CACHE_WAIT: begin
- CACHE_BUS_RRQr <= 1'b0;
- if(~CACHE_BUS_RRQr & BUS_RDY) begin
- CACHE_ST <= ST_CACHE_ADDR;
- cx4_pgmrom_we <= 1'b1;
- cache_count <= cache_count + 1;
- end else CACHE_ST <= ST_CACHE_WAIT;
- end
- ST_CACHE_ADDR: begin
- cx4_pgmrom_we <= 1'b0;
- CACHE_SRC_ADDRr <= CACHE_SRC_ADDRr + 1;
- cx4_pgmrom_addr <= cx4_pgmrom_addr + 1;
- if(cache_count == 9'h1ff) begin
- cx4_busy[BUSY_CACHE] <= 1'b0;
- cachetag[cache_cachepage] <= cache_pgmpage;
- cachevalid[cache_cachepage] <= 1'b1;
- CACHE_ST <= ST_CACHE_IDLE;
- end else begin
- CACHE_BUS_RRQr <= 1'b1;
- CACHE_ST <= ST_CACHE_WAIT;
- end
- end
- endcase
- end
- reg cx4_dma_datram_we;
- reg cx4_cpu_datram_we;
- initial cx4_dma_datram_we = 1'b0;
- initial cx4_cpu_datram_we = 1'b0;
- wire cx4_datram_we = cx4_dma_datram_we | cx4_cpu_datram_we;
- reg [11:0] cx4_dma_datram_addr;
- reg [11:0] cx4_cpu_datram_addr;
- wire [11:0] cx4_datram_addr = cx4_busy[BUSY_DMA] ? cx4_dma_datram_addr : cx4_cpu_datram_addr;
- reg [23:0] cx4_cpu_datram_di;
- wire [7:0] cx4_datram_di = cx4_busy[BUSY_DMA] ? BUS_DI : cx4_cpu_datram_di;
- reg [15:0] dma_count;
- initial dma_count = 16'b0;
- always @(posedge CLK) begin
- case(DMA_ST)
- ST_DMA_IDLE: begin
- if(DMA_TRIG_EN) begin
- DMA_ST <= ST_DMA_START;
- end else DMA_ST <= ST_DMA_IDLE;
- end
- ST_DMA_START: begin
- cx4_busy[BUSY_DMA] <= 1'b1;
- DMA_SRC_ADDRr <= cx4_mmio_dmasrc;
- cx4_dma_datram_addr <= (cx4_mmio_dmatgt & 24'h000fff);
- DMA_ST <= ST_DMA_WAIT;
- dma_count <= cx4_mmio_dmalen;
- DMA_BUS_RRQr <= 1'b1;
- end
- ST_DMA_WAIT: begin
- DMA_BUS_RRQr <= 1'b0;
- if(~DMA_BUS_RRQr & BUS_RDY) begin
- DMA_ST <= ST_DMA_ADDR;
- cx4_dma_datram_we <= 1'b1;
- dma_count <= dma_count - 1;
- end else DMA_ST <= ST_DMA_WAIT;
- end
- ST_DMA_ADDR: begin
- cx4_dma_datram_we <= 1'b0;
- DMA_SRC_ADDRr <= DMA_SRC_ADDRr + 1;
- cx4_dma_datram_addr <= cx4_dma_datram_addr + 1;
- if(dma_count == 16'h0000) begin
- cx4_busy[BUSY_DMA] <= 1'b0;
- DMA_ST <= ST_DMA_IDLE;
- end else begin
- DMA_BUS_RRQr <= 1'b1;
- DMA_ST <= ST_DMA_WAIT;
- end
- end
- endcase
- end
- /***************************
- =========== CPU ===========
- ***************************/
- reg [5:0] CPU_STATE;
- reg [2:0] cpu_sp;
- initial cpu_sp = 3'b000;
- wire [15:0] cpu_op_w;
- reg [15:0] cpu_op;
- reg [23:0] cpu_busdata;
- reg [23:0] cpu_romdata;
- reg [23:0] cpu_ramdata;
- reg [23:0] cpu_busaddr;
- assign MAPPED_CPU_BUS_ADDR = {cpu_busaddr[23:16], cpu_busaddr[14:0]};
- reg [23:0] cpu_romaddr;
- reg [23:0] cpu_ramaddr;
- reg [23:0] cpu_acch;
- reg [23:0] cpu_accl;
- reg [23:0] cpu_mul_src;
- reg [24:0] cpu_alu_res;
- reg [23:0] cpu_dummy;
- reg [23:0] cpu_tmp;
- reg [23:0] cpu_sa; // tmp register for shifted accumulator
- reg [7:0] cpu_wait;
- initial cpu_wait = 8'h00;
- wire [9:0] cx4_datrom_addr = cpu_a[9:0];
- wire [23:0] cx4_datrom_do;
- wire [7:0] cx4_datram_do;
- parameter ST_CPU_IDLE = 6'b000001;
- parameter ST_CPU_0 = 6'b000010;
- parameter ST_CPU_1 = 6'b000100;
- parameter ST_CPU_2 = 6'b001000;
- parameter ST_CPU_3 = 6'b010000;
- parameter ST_CPU_4 = 6'b100000;
- initial CPU_STATE = ST_CPU_IDLE;
- parameter OP_NOP = 5'b00000;
- parameter OP_JP = 5'b00001;
- parameter OP_SKIP = 5'b00010;
- parameter OP_RT = 5'b00011;
- parameter OP_LD = 5'b00100;
- parameter OP_ST = 5'b00101;
- parameter OP_SWP = 5'b00110;
- parameter OP_RDROM = 5'b00111;
- parameter OP_RDRAM = 5'b01000;
- parameter OP_WRRAM = 5'b01001;
- parameter OP_ALU = 5'b01010;
- parameter OP_MUL = 5'b01011;
- parameter OP_WAI = 5'b01100;
- parameter OP_BUS = 5'b01101;
- parameter OP_CMP = 5'b01110;
- parameter OP_SEX = 5'b01111;
- parameter OP_HLT = 5'b10000;
- wire [6:0] op_id = cpu_op_w[15:10];
- reg [7:0] op_param;
- reg [4:0] op;
- reg [1:0] op_sa;
- reg op_imm;
- reg op_p;
- reg op_call;
- reg op_jump;
- reg condtrue;
- always @(posedge CLK) begin
- if(cpu_go_en_r) cx4_busy[BUSY_CPU] <= 1'b1;
- else if(op == OP_HLT) cx4_busy[BUSY_CPU] <= 1'b0;
- end
- always @(posedge CLK) begin
- case(op_sa)
- 2'b00: cpu_sa <= cpu_a;
- 2'b01: cpu_sa <= cpu_a << 1;
- 2'b10: cpu_sa <= cpu_a << 8;
- 2'b11: cpu_sa <= cpu_a << 16;
- endcase
- end
- reg jp_docache;
- initial jp_docache = 1'b0;
- always @(posedge CLK) begin
- case(CPU_STATE)
- ST_CPU_IDLE: begin
- if(cpu_go_en_r) begin
- cpu_pc <= cx4_mmio_pc;
- cpu_page <= cx4_mmio_cachepage;
- cpu_p <= cx4_mmio_pgmpage;
- op <= OP_NOP;
- CPU_STATE <= ST_CPU_2;
- end
- else CPU_STATE <= ST_CPU_IDLE;
- end
- ST_CPU_0: begin // Phase 0:
- cpu_cache_en <= 1'b0;
- if(op == OP_HLT) begin
- CPU_STATE <= ST_CPU_IDLE;
- end
- else CPU_STATE <= ST_CPU_1;
- case(op)
- OP_JP: begin
- case(cpu_op[11:10])
- 2'b10: condtrue <= 1'b1;
- 2'b11: condtrue <= fl_z;
- 2'b00: condtrue <= fl_c;
- 2'b01: condtrue <= fl_n;
- endcase
- if(op_p && !jp_docache) begin
- jp_docache <= 1'b1;
- cpu_cache_en <= 1'b1;
- end
- end
- OP_SKIP: begin
- case(cpu_op[9:8])
- 2'b01: condtrue <= (fl_c == cpu_op[0]);
- 2'b10: condtrue <= (fl_z == cpu_op[0]);
- 2'b11: condtrue <= (fl_n == cpu_op[0]);
- endcase
- end
- OP_LD, OP_ALU, OP_MUL, OP_CMP, OP_SEX: begin
- if(op_imm) cpu_idb <= {16'b0, op_param};
- else casex(op_param)
- 8'h00: cpu_idb <= cpu_a;
- 8'h01: cpu_idb <= cpu_acch;
- 8'h02: cpu_idb <= cpu_accl;
- 8'h03: cpu_idb <= cpu_busdata;
- 8'h08: cpu_idb <= cpu_romdata;
- 8'h0c: cpu_idb <= cpu_ramdata;
- 8'h13: cpu_idb <= cpu_busaddr;
- 8'h1c: cpu_idb <= cpu_ramaddr;
- 8'h5x: cpu_idb <= const[op_param[3:0]];
- 8'h6x: cpu_idb <= {gpr[op_param[3:0]*3+2],
- gpr[op_param[3:0]*3+1],
- gpr[op_param[3:0]*3]};
- default: cpu_idb <= 24'b0;
- endcase
- end
- OP_ST: begin
- cpu_idb <= cpu_a;
- end
- OP_SWP: begin
- cpu_idb <= cpu_a;
- casex(op_param)
- 8'h00: cpu_tmp <= cpu_a;
- 8'h01: cpu_tmp <= cpu_acch;
- 8'h02: cpu_tmp <= cpu_accl;
- 8'h03: cpu_tmp <= cpu_busdata;
- 8'h08: cpu_tmp <= cpu_romdata;
- 8'h0c: cpu_tmp <= cpu_ramdata;
- 8'h13: cpu_tmp <= cpu_busaddr;
- 8'h1c: cpu_tmp <= cpu_ramaddr;
- 8'h5x: cpu_tmp <= const[op_param[3:0]];
- 8'h6x: cpu_tmp <= {gpr[op_param[3:0]*3+2],
- gpr[op_param[3:0]*3+1],
- gpr[op_param[3:0]*3]};
- default: cpu_tmp <= 24'b0;
- endcase
- end
- OP_RDRAM, OP_WRRAM: begin
- if(op_imm) cx4_cpu_datram_addr <= {16'b0, op_param} + cpu_ramaddr;
- else casex(op_param)
- 8'h00: cx4_cpu_datram_addr <= cpu_a;
- 8'h01: cx4_cpu_datram_addr <= cpu_acch;
- 8'h02: cx4_cpu_datram_addr <= cpu_accl;
- 8'h03: cx4_cpu_datram_addr <= cpu_busdata;
- 8'h08: cx4_cpu_datram_addr <= cpu_romdata;
- 8'h0c: cx4_cpu_datram_addr <= cpu_ramdata;
- 8'h13: cx4_cpu_datram_addr <= cpu_busaddr;
- 8'h1c: cx4_cpu_datram_addr <= cpu_ramaddr;
- 8'h5x: cx4_cpu_datram_addr <= const[op_param[3:0]];
- 8'h6x: cx4_cpu_datram_addr <= {gpr[op_param[3:0]*3+2],
- gpr[op_param[3:0]*3+1],
- gpr[op_param[3:0]*3]};
- default: cx4_cpu_datram_addr <= 24'b0;
- endcase
- end
- OP_BUS: cpu_bus_rq <= 1'b1;
- endcase
- end
- ST_CPU_1: begin
- CPU_STATE <= ST_CPU_2;
- condtrue <= 1'b0;
- case(op)
- OP_JP: begin
- cpu_cache_en <= 1'b0;
- if(!cpu_cache_en && !cx4_busy[BUSY_CACHE]) begin
- jp_docache <= 1'b0;
- if(condtrue) begin
- if(op_call) begin
- cpu_page_stack[cpu_sp] <= cpu_page;
- cpu_pc_stack[cpu_sp] <= cpu_pc + 1;
- cpu_sp <= cpu_sp + 1;
- end
- cpu_pc <= op_param;
- cpu_page <= cpu_page ^ op_p;
- end else cpu_pc <= cpu_pc + 1;
- end
- end
- OP_SKIP: begin
- if(condtrue) cpu_pc <= cpu_pc + 2;
- else cpu_pc <= cpu_pc + 1;
- end
- OP_RT: begin
- cpu_page <= cpu_page_stack[cpu_sp - 1];
- cpu_pc <= cpu_pc_stack[cpu_sp - 1];
- cpu_sp <= cpu_sp - 1;
- end
- OP_WAI: if(BUS_RDY) cpu_pc <= cpu_pc + 1;
- OP_BUS: begin
- cpu_bus_rq <= 1'b0;
- cpu_pc <= cpu_pc + 1;
- end
- default: cpu_pc <= cpu_pc + 1;
- endcase
- end
- ST_CPU_2: begin
- CPU_STATE <= ST_CPU_3;
- case(op)
- OP_LD: begin
- casex(cpu_op[11:8])
- 4'b0x00: cpu_a <= cpu_idb;
- 4'b0x11: cpu_p <= cpu_idb;
- 4'b1100: cpu_p[7:0] <= op_param;
- 4'b1101: cpu_p[14:8] <= op_param;
- endcase
- end
- OP_ST, OP_SWP: begin
- casex(op_param)
- 8'h01: cpu_acch <= cpu_idb;
- 8'h02: cpu_accl <= cpu_idb;
- 8'h08: cpu_romdata <= cpu_idb;
- 8'h0c: cpu_ramdata <= cpu_idb;
- 8'h13: cpu_busaddr <= cpu_idb;
- 8'h1c: cpu_ramaddr <= cpu_idb;
- endcase
- if(op==OP_SWP) cpu_a <= cpu_tmp;
- end
- OP_RDROM: cpu_romdata <= cx4_datrom_do;
- OP_RDRAM: begin
- case(cpu_op[9:8])
- 2'b00: cpu_ramdata[7:0] <= cx4_datram_do;
- 2'b01: cpu_ramdata[15:8] <= cx4_datram_do;
- 2'b10: cpu_ramdata[23:16] <= cx4_datram_do;
- endcase
- end
- OP_WRRAM: begin
- case(cpu_op[9:8])
- 2'b00: cx4_cpu_datram_di <= cpu_ramdata[7:0];
- 2'b01: cx4_cpu_datram_di <= cpu_ramdata[15:8];
- 2'b10: cx4_cpu_datram_di <= cpu_ramdata[23:16];
- endcase
- cx4_cpu_datram_we <= 1'b1;
- end
- OP_CMP: begin
- case(cpu_op[15:11])
- 5'b01001: cpu_alu_res <= cpu_idb - cpu_sa;
- 5'b01010: cpu_alu_res <= cpu_sa - cpu_idb;
- endcase
- end
- OP_SEX: begin
- case(cpu_op[9:8])
- 2'b01: cpu_alu_res <= {{16{cpu_idb[7]}}, cpu_idb[7:0]};
- 2'b10: cpu_alu_res <= {{8{cpu_idb[15]}}, cpu_idb[15:0]};
- endcase
- end
- OP_ALU: begin
- case(cpu_op[15:11])
- 5'b10000: cpu_alu_res <= cpu_sa + cpu_idb;
- 5'b10001: cpu_alu_res <= cpu_idb - cpu_sa;
- 5'b10010: cpu_alu_res <= cpu_sa - cpu_idb;
- 5'b10101: cpu_alu_res <= cpu_sa ^ cpu_idb;
- 5'b10110: cpu_alu_res <= cpu_sa & cpu_idb;
- 5'b10111: cpu_alu_res <= cpu_sa | cpu_idb;
- 5'b11000: cpu_alu_res <= cpu_a >> cpu_idb;
- 5'b11001: cpu_alu_res <= ($signed(cpu_a)) >>> cpu_idb;
- 5'b11010: {cpu_dummy, cpu_alu_res[23:0]} <= {cpu_a, cpu_a} >> cpu_idb;
- 5'b11011: cpu_alu_res <= cpu_a << cpu_idb;
- endcase
- end
- endcase
- end
- ST_CPU_3: begin
- case(op)
- OP_BUS: cpu_busaddr <= cpu_busaddr + 1;
- OP_WRRAM: cx4_cpu_datram_we <= 1'b0;
- OP_CMP: begin
- fl_n <= cpu_alu_res[23];
- fl_z <= cpu_alu_res[23:0] == 24'b0;
- fl_c <= ~cpu_alu_res[24];
- end
- OP_SEX: cpu_a <= cpu_alu_res[23:0];
- OP_ALU: begin
- cpu_a <= cpu_alu_res[23:0];
- case(cpu_op[15:11])
- 5'b10000: begin
- fl_n <= cpu_alu_res[23];
- fl_z <= cpu_alu_res[23:0] == 24'b0;
- fl_c <= cpu_alu_res[24];
- end
- 5'b10001, 5'b10010: begin
- fl_n <= cpu_alu_res[23];
- fl_z <= cpu_alu_res[23:0] == 24'b0;
- fl_c <= ~cpu_alu_res[24];
- end
- default: begin
- fl_n <= cpu_alu_res[23];
- fl_z <= cpu_alu_res[23:0] == 24'b0;
- end
- endcase
- end
- OP_MUL: begin
- cpu_acch <= cpu_mul_result[47:24];
- cpu_accl <= cpu_mul_result[23:0];
- fl_z <= (cpu_mul_result == 48'b0);
- fl_n <= cpu_mul_result[47];
- end
- endcase
- cpu_op <= cpu_op_w;
- casex(cpu_op_w[15:11])
- 5'b00x01, 5'b00x10, 5'b00100, 5'b00111: begin
- cpu_wait <= 8'h08;
- CPU_STATE <= ST_CPU_4;
- end
- 5'b01110, 5'b01101, 5'b11101: begin
- cpu_wait <= 8'h03;
- CPU_STATE <= ST_CPU_4;
- end
- 5'b10011: begin
- cpu_wait <= 8'h03;
- CPU_STATE <= ST_CPU_4;
- end
- 5'b01000: begin
- cpu_wait <= 8'h13;
- CPU_STATE <= ST_CPU_4;
- end
- default: begin
- cpu_wait <= 8'h00;
- CPU_STATE <= ST_CPU_0;
- end
- endcase
-
- casex(cpu_op_w[15:11])
- 5'b00000: op <= OP_NOP;
- 5'b00x01: op <= OP_JP;
- 5'b00x10: op <= OP_JP;
- 5'b00100: op <= OP_SKIP;
- 5'b00111: op <= OP_RT;
- 5'b01100: op <= OP_LD;
- 5'b01111: op <= OP_LD;
- 5'b11100: op <= OP_ST;
- 5'b11110: op <= OP_SWP;
- 5'b01110: op <= OP_RDROM;
- 5'b01101: op <= OP_RDRAM;
- 5'b11101: op <= OP_WRRAM;
- 5'b01001: op <= OP_CMP;
- 5'b01010: op <= OP_CMP;
- 5'b01011: op <= OP_SEX;
- 5'b10000: op <= OP_ALU;
- 5'b10001: op <= OP_ALU;
- 5'b10010: op <= OP_ALU;
- 5'b10101: op <= OP_ALU;
- 5'b10110: op <= OP_ALU;
- 5'b10111: op <= OP_ALU;
- 5'b11000: op <= OP_ALU;
- 5'b11001: op <= OP_ALU;
- 5'b11010: op <= OP_ALU;
- 5'b11011: op <= OP_ALU;
- 5'b10011: op <= OP_MUL;
-
- 5'b00011: op <= OP_WAI;
- 5'b01000: op <= OP_BUS;
-
- 5'b11111: op <= OP_HLT;
- endcase
- op_imm <= cpu_op_w[10];
- op_p <= cpu_op_w[9];
- op_call <= cpu_op_w[13];
- op_param <= cpu_op_w[7:0];
- op_sa <= cpu_op_w[9:8];
- end
- ST_CPU_4: begin
- cpu_wait <= cpu_wait - 1;
- if(cpu_wait) CPU_STATE <= ST_CPU_4;
- else CPU_STATE <= ST_CPU_0;
- end
- endcase
- end
- reg[2:0] BUSRD_STATE;
- parameter ST_BUSRD_IDLE = 3'b001;
- parameter ST_BUSRD_WAIT = 3'b010;
- parameter ST_BUSRD_END = 3'b100;
- initial BUSRD_STATE = ST_BUSRD_IDLE;
- reg cpu_bus_rq2;
- always @(posedge CLK) cpu_bus_rq2 <= cpu_bus_rq;
- always @(posedge CLK) begin
- if(CPU_STATE == ST_CPU_2
- && (op == OP_ST || op == OP_SWP)
- && op_param == 8'h03)
- cpu_busdata <= cpu_idb;
- else begin
- case(BUSRD_STATE)
- ST_BUSRD_IDLE: begin
- if(cpu_bus_rq2) begin
- BUSRD_STATE <= ST_BUSRD_WAIT;
- end
- end
- ST_BUSRD_WAIT: begin
- if(BUS_RDY) BUSRD_STATE <= ST_BUSRD_END;
- else BUSRD_STATE <= ST_BUSRD_WAIT;
- end
- ST_BUSRD_END: begin
- if(~cpu_busaddr[22]) cpu_busdata <= BUS_DI;
- else cpu_busdata <= 8'h00;
- end
- endcase
- end
- end
- // gpr write, either by CPU or by MMIO
- always @(posedge CLK) begin
- if(CPU_STATE == ST_CPU_2
- && (op == OP_ST || op == OP_SWP)
- && (op_param[7:4] == 4'h6)) begin
- gpr[op_param[3:0]*3+2] <= cpu_idb[23:16];
- gpr[op_param[3:0]*3+1] <= cpu_idb[15:8];
- gpr[op_param[3:0]*3] <= cpu_idb[7:0];
- end
- else if(GPR_WR_EN) gpr[ADDR[5:0]] <= DIr;
- end
- /***************************
- =========== MEM ===========
- ***************************/
- cx4_datrom cx4_datrom (
- .clka(CLK), // input clka
- .wea(DATROM_WE), // input [0 : 0] wea
- .addra(DATROM_ADDR), // input [9 : 0] addra
- .dina(DATROM_DI), // input [23 : 0] dina
- .clkb(CLK), // input clkb
- .addrb(cx4_datrom_addr), // input [9 : 0] addrb
- .doutb(cx4_datrom_do) // output [23 : 0] doutb
- );
- cx4_datram cx4_datram (
- .clka(CLK), // input clka
- .wea(DATRAM_WR_EN), // input [0 : 0] wea
- .addra(ADDR[11:0]), // input [11 : 0] addra
- .dina(DIr), // input [7 : 0] dina
- .douta(DATRAM_DO), // output [7 : 0] douta
- .clkb(CLK), // input clkb
- .web(cx4_datram_we), // input [0 : 0] web
- .addrb(cx4_datram_addr), // input [11 : 0] addrb
- .dinb(cx4_datram_di), // input [7 : 0] dinb
- .doutb(cx4_datram_do) // output [7 : 0] doutb
- );
- cx4_pgmrom cx4_pgmrom (
- .clka(CLK), // input clka
- .wea(cx4_pgmrom_we), // input [0 : 0] wea
- .addra(cx4_pgmrom_addr), // input [9 : 0] addra
- .dina(BUS_DI), // input [7 : 0] dina
- .clkb(CLK), // input clkb
- .addrb({cpu_page,cpu_pc}), // input [8 : 0] addrb
- .doutb(cpu_op_w) // output [15 : 0] doutb
- );
- cx4_mul cx4_mul (
- .clk(CLK), // input clk
- .a(cpu_a), // input [23 : 0] a
- .b(cpu_idb), // input [23 : 0] b
- .p(cpu_mul_result) // output [47 : 0] p
- );
- endmodule
|