diff --git a/verilog/sd2snes_cx4/cx4.v b/verilog/sd2snes_cx4/cx4.v index 97286be..6d62b47 100644 --- a/verilog/sd2snes_cx4/cx4.v +++ b/verilog/sd2snes_cx4/cx4.v @@ -19,22 +19,22 @@ // ////////////////////////////////////////////////////////////////////////////////// module cx4( - input [7:0] DI, - output [7:0] DO, - input [12:0] ADDR, - input CS, - 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 - ); + input [7:0] DI, + output [7:0] DO, + input [12:0] ADDR, + input CS, + 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; @@ -57,10 +57,10 @@ 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; + : status_enable ? STATUS_DO + : vector_enable ? VECTOR_DO + : gpr_enable ? GPR_DO + : 8'h00; /* 0x1f40 - 0x1f52: MMIO SNES: 8 bits / CX4: various */ @@ -138,8 +138,8 @@ 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) + AND (selected cache page is invalid + OR selected cache page does not contain requested page already) */ reg CACHE_TRIG_ENr; reg CACHE_TRIG_EN2r; @@ -162,6 +162,9 @@ initial begin end assign BUS_RRQ = CACHE_BUS_RRQr | DMA_BUS_RRQr; +reg cpu_go_en_r; +initial cpu_go_en_r = 1'b0; + initial begin cx4_mmio_r1f50 = 8'h33; cx4_mmio_r1f51 = 1'b0; @@ -170,74 +173,78 @@ 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_r1f4c}; // 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'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_r1f4c}; // 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 - - 5'h13: MMIO_DOr <= cpu_mul_result[47:40]; // 1f40 - 5'h14: MMIO_DOr <= cpu_mul_result[39:32]; // 1f40 - 5'h15: MMIO_DOr <= cpu_mul_result[31:24]; // 1f40 - 5'h16: MMIO_DOr <= cpu_mul_result[23:16]; // 1f40 - 5'h17: MMIO_DOr <= cpu_mul_result[15:8]; // 1f40 - 5'h18: MMIO_DOr <= cpu_mul_result[7:0]; // 1f40 + 5'h12: MMIO_DOr <= {7'b0, cx4_mmio_r1f52}; // 1f52 - -// 5'h14: MMIO_DOr <= cachetag[0][15:8]; // 1f40 -// 5'h15: MMIO_DOr <= cachetag[0][7:0]; // 1f41 -// 5'h16: MMIO_DOr <= cachetag[1][15:8]; // 1f42 -// 5'h17: MMIO_DOr <= cachetag[1][7:0]; // 1f43 - default: MMIO_DOr <= 8'hff; + 5'h13: MMIO_DOr <= cpu_mul_result[47:40]; // 1f40 + 5'h14: MMIO_DOr <= cpu_mul_result[39:32]; // 1f40 + 5'h15: MMIO_DOr <= cpu_mul_result[31:24]; // 1f40 + 5'h16: MMIO_DOr <= cpu_mul_result[23:16]; // 1f40 + 5'h17: MMIO_DOr <= cpu_mul_result[15:8]; // 1f40 + 5'h18: MMIO_DOr <= cpu_mul_result[7:0]; // 1f40 + + +// 5'h14: MMIO_DOr <= cachetag[0][15:8]; // 1f40 +// 5'h15: MMIO_DOr <= cachetag[0][7:0]; // 1f41 +// 5'h16: MMIO_DOr <= cachetag[1][15:8]; // 1f42 +// 5'h17: MMIO_DOr <= cachetag[1][7:0]; // 1f43 + 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] <= DI; // 1f40 - 5'h01: cx4_mmio_dmasrc[15:8] <= DI; // 1f41 - 5'h02: cx4_mmio_dmasrc[23:16] <= DI; // 1f42 - 5'h03: cx4_mmio_dmalen[7:0] <= DI; // 1f43 - 5'h04: cx4_mmio_dmalen[15:8] <= DI; // 1f44 - 5'h05: cx4_mmio_dmatgt[7:0] <= DI; // 1f45 - 5'h06: cx4_mmio_dmatgt[15:8] <= DI; // 1f46 - 5'h07: begin - cx4_mmio_dmatgt[23:16] <= DI; // 1f47 - DMA_TRIG_ENr <= 1'b1; - end - 5'h08: begin - cx4_mmio_cachepage <= DI[0]; // 1f48 - CACHE_TRIG_ENr <= 1'b1; - end - 5'h09: cx4_mmio_pgmoff[7:0] <= DI; // 1f49 - 5'h0a: cx4_mmio_pgmoff[15:8] <= DI; // 1f4a - 5'h0b: cx4_mmio_pgmoff[23:16] <= DI; // 1f4b - 5'h0c: cx4_mmio_r1f4c <= DI[1:0]; // 1f4c - 5'h0d: cx4_mmio_pgmpage[7:0] <= DI; // 1f4d - 5'h0e: cx4_mmio_pgmpage[14:8] <= DI[6:0]; // 1f4e - 5'h0f: cx4_mmio_pc <= DI; // 1f4f - 5'h10: cx4_mmio_r1f50 <= DI & 8'h77; // 1f50 - 5'h11: cx4_mmio_r1f51 <= DI[0]; // 1f51 - 5'h12: cx4_mmio_r1f52 <= DI[0]; // 1f52 - endcase + 5'h00: cx4_mmio_dmasrc[7:0] <= DI; // 1f40 + 5'h01: cx4_mmio_dmasrc[15:8] <= DI; // 1f41 + 5'h02: cx4_mmio_dmasrc[23:16] <= DI; // 1f42 + 5'h03: cx4_mmio_dmalen[7:0] <= DI; // 1f43 + 5'h04: cx4_mmio_dmalen[15:8] <= DI; // 1f44 + 5'h05: cx4_mmio_dmatgt[7:0] <= DI; // 1f45 + 5'h06: cx4_mmio_dmatgt[15:8] <= DI; // 1f46 + 5'h07: begin + cx4_mmio_dmatgt[23:16] <= DI; // 1f47 + DMA_TRIG_ENr <= 1'b1; + end + 5'h08: begin + cx4_mmio_cachepage <= DI[0]; // 1f48 + CACHE_TRIG_ENr <= 1'b1; + end + 5'h09: cx4_mmio_pgmoff[7:0] <= DI; // 1f49 + 5'h0a: cx4_mmio_pgmoff[15:8] <= DI; // 1f4a + 5'h0b: cx4_mmio_pgmoff[23:16] <= DI; // 1f4b + 5'h0c: cx4_mmio_r1f4c <= DI[1:0]; // 1f4c + 5'h0d: cx4_mmio_pgmpage[7:0] <= DI; // 1f4d + 5'h0e: cx4_mmio_pgmpage[14:8] <= DI[6:0]; // 1f4e + 5'h0f: begin + cx4_mmio_pc <= DI; // 1f4f + cpu_go_en_r <= 1'b1; + end + 5'h10: cx4_mmio_r1f50 <= DI & 8'h77; // 1f50 + 5'h11: cx4_mmio_r1f51 <= DI[0]; // 1f51 + 5'h12: cx4_mmio_r1f52 <= DI[0]; // 1f52 + endcase end else begin CACHE_TRIG_ENr <= 1'b0; - DMA_TRIG_ENr <= 1'b0; + DMA_TRIG_ENr <= 1'b0; + cpu_go_en_r <= 1'b0; end end @@ -245,10 +252,6 @@ always @(posedge CLK) begin if(VECTOR_WR_EN) vector[ADDR[4:0]] <= DI; end -always @(posedge CLK) begin - if(GPR_WR_EN) gpr[ADDR[5:0]] <= DI; -end - reg [4:0] CACHE_ST; parameter ST_CACHE_IDLE = 5'b00001; parameter ST_CACHE_START = 5'b00010; @@ -272,7 +275,7 @@ wire [22:0] MAPPED_DMA_SRC_ADDR = {DMA_SRC_ADDRr[23:16],DMA_SRC_ADDRr[14:0]}; assign BUS_ADDR = cx4_busy[BUSY_CACHE] ? MAPPED_CACHE_SRC_ADDR : cx4_busy[BUSY_DMA] ? MAPPED_DMA_SRC_ADDR - : 24'h000000 /* XXX cx4_bus_addr */; + : 24'h800000 /* XXX cx4_bus_addr */; reg cx4_pgmrom_we; initial cx4_pgmrom_we = 1'b0; @@ -282,97 +285,101 @@ initial cache_count = 20'b0; always @(posedge CLK) begin case(CACHE_ST) - ST_CACHE_IDLE: begin - if(CACHE_TRIG_EN - & (~cachetag[cx4_mmio_cachepage][15] - | |(cachetag[cx4_mmio_cachepage][14:0] ^ cx4_mmio_pgmpage))) + ST_CACHE_IDLE: begin + if(CACHE_TRIG_EN + & (~cachetag[cx4_mmio_cachepage][15] + | |(cachetag[cx4_mmio_cachepage][14:0] ^ cx4_mmio_pgmpage))) begin - CACHE_ST <= ST_CACHE_START; - end else CACHE_ST <= ST_CACHE_IDLE; - end - ST_CACHE_START: begin - cx4_busy[BUSY_CACHE] <= 1'b1; - CACHE_SRC_ADDRr <= cx4_mmio_pgmoff + {cx4_mmio_pgmpage, 9'b0}; - cx4_pgmrom_addr <= {cx4_mmio_cachepage, 9'b0}; - CACHE_ST <= ST_CACHE_WAIT; - cache_count <= 10'b0; + CACHE_ST <= ST_CACHE_START; + end else CACHE_ST <= ST_CACHE_IDLE; + end + ST_CACHE_START: begin + cx4_busy[BUSY_CACHE] <= 1'b1; + CACHE_SRC_ADDRr <= cx4_mmio_pgmoff + {cx4_mmio_pgmpage, 9'b0}; + cx4_pgmrom_addr <= {cx4_mmio_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[cx4_mmio_cachepage] <= {1'b1,cx4_mmio_pgmpage}; - CACHE_ST <= ST_CACHE_IDLE; - end else begin - CACHE_BUS_RRQr <= 1'b1; - CACHE_ST <= ST_CACHE_WAIT; - end - end + 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[cx4_mmio_cachepage] <= {1'b1,cx4_mmio_pgmpage}; + CACHE_ST <= ST_CACHE_IDLE; + end else begin + CACHE_BUS_RRQr <= 1'b1; + CACHE_ST <= ST_CACHE_WAIT; + end + end endcase end -reg cx4_datram_we; -initial cx4_datram_we = 1'b0; -reg [11:0] cx4_datram_addr; +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 [23: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; - /* XXX Rename to DMA_TGT_ADDRr and switch */ - cx4_datram_addr <= (cx4_mmio_dmatgt & 24'h000fff); - DMA_ST <= ST_DMA_WAIT; - dma_count <= cx4_mmio_dmalen; + 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; - /* XXX Rename to DMA_TGT_WEr and switch */ - cx4_datram_we <= 1'b1; - dma_count <= dma_count - 1; - end else DMA_ST <= ST_DMA_WAIT; - end - ST_DMA_ADDR: begin - /* XXX Rename to DMA_TGT_WEr and switch */ - cx4_datram_we <= 1'b0; - DMA_SRC_ADDRr <= DMA_SRC_ADDRr + 1; - cx4_datram_addr <= cx4_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 + 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 [7:0] CPU_STATE; +reg [4:0] CPU_STATE; reg cpu_page; reg [7:0] cpu_pc; reg [8:0] cpu_stack [7:0]; @@ -396,200 +403,284 @@ reg fl_z; reg fl_c; reg [15:0] cpu_p; -reg [9:0] cx4_datrom_addr; +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 = 8'b00000001; -parameter ST_CPU_0 = 8'b00000010; -parameter ST_CPU_1 = 8'b00000100; -parameter ST_CPU_2 = 8'b00001000; -parameter ST_CPU_3 = 8'b00010000; +parameter ST_CPU_IDLE = 5'b00001; +parameter ST_CPU_0 = 5'b00010; +parameter ST_CPU_1 = 5'b00100; +parameter ST_CPU_2 = 5'b01000; +parameter ST_CPU_3 = 5'b10000; initial CPU_STATE <= ST_CPU_IDLE; -parameter OP_ALU = 4'b0000; -parameter OP_LD = 4'b0001; -parameter OP_ST = 4'b0010; -parameter OP_JP = 4'b0011; -parameter OP_SWP = 4'b0100; -parameter OP_HLT = 4'b0101; -parameter OP_BUS = 4'b0110; -parameter OP_STA = 4'b0111; -parameter OP_NOP = 4'b1111; - +parameter OP_NOP = 4'b0000; +parameter OP_JP = 4'b0001; +parameter OP_SKIP = 4'b0010; +parameter OP_RT = 4'b0011; +parameter OP_LD = 4'b0100; +parameter OP_ST = 4'b0101; +parameter OP_SWP = 4'b0110; +parameter OP_RDROM = 4'b0111; +parameter OP_RDRAM = 4'b1000; +parameter OP_WRRAM = 4'b1001; +parameter OP_ALU = 4'b1010; +parameter OP_MUL = 4'b1011; +parameter OP_WAI = 4'b1100; +parameter OP_BUS = 4'b1101; +parameter OP_HLT = 4'b1110; wire [6:0] op_id = cpu_op_w[15:10]; reg [7:0] op_param; -reg [2:0] op; +reg [3:0] op; reg [1:0] op_sa; reg op_imm; reg op_p; reg op_call; reg op_jump; -reg cond_true; -reg cpu_go_rq; +reg condtrue; reg cpu_bus_rq; always @(posedge CLK) begin case(CPU_STATE) ST_CPU_IDLE: begin - if(cpu_go_rq) begin - cpu_pc <= cx4_mmio_pc; - op <= OP_NOP; - CPU_STATE <= ST_CPU_2; - end - else CPU_STATE <= ST_CPU_IDLE; - end - ST_CPU_0: begin // Phase 0: - CPU_STATE <= ST_CPU_1; + if(cpu_go_en_r) begin + cpu_pc <= cx4_mmio_pc; + op <= OP_NOP; + CPU_STATE <= ST_CPU_2; + cx4_busy[BUSY_CPU] <= 1'b1; + end + else CPU_STATE <= ST_CPU_IDLE; + end + ST_CPU_0: begin // Phase 0: + if(op == OP_HLT) begin + cx4_busy[BUSY_CPU] <= 1'b0; + CPU_STATE <= ST_CPU_IDLE; + end + else CPU_STATE <= ST_CPU_1; case(op) - OP_ALU, OP_LD, OP_SWP: begin - if(cpu_op[15:10] == 6'b111000) cpu_idb <= cpu_a; // reg[imm] <- a - else 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 - if(op==OP_ALU) 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 - end - OP_JP: begin - casex(cpu_op[12:8]) - 5'b010xx: cond_true <= 1'b1; - 5'b011xx: cond_true <= fl_z; - 5'b100xx: cond_true <= fl_c; - 5'b101xx: cond_true <= fl_n; - 5'b00101: cond_true <= (fl_c == cpu_op[0]); - 5'b00110: cond_true <= (fl_z == cpu_op[0]); - 5'b00111: cond_true <= (fl_n == cpu_op[0]); - default: cond_true <= 1'b1; - endcase - end - OP_BUS: cpu_bus_rq <= 1'b1; - endcase - end - ST_CPU_1: begin - CPU_STATE <= ST_CPU_2; - case(op) - OP_LD: begin - cx4_datram_addr <= op_imm ? op_param : (cpu_ramaddr + cpu_idb); - cx4_datrom_addr <= cpu_a[9:0]; - end - OP_ST: begin - cx4_datram_addr <= op_imm ? op_param : (cpu_ramaddr + cpu_idb); - cx4_datram_we <= 1'b1; - end - OP_JP: begin - if(cond_true) begin - casex(cpu_op[12:11]) - 2'b01, 2'b10: begin - // TODO if(op_p) - if(op_call) begin - cpu_stack[cpu_sp] <= {cpu_page, cpu_pc+1}; - cpu_sp <= cpu_sp - 1; - end - cpu_pc <= op_param; - end - 2'b00: begin - cpu_pc <= cpu_pc + 2; - end - 2'b11: begin - if(cpu_op[13]) begin - {cpu_page, cpu_pc} <= cpu_stack[cpu_sp+1]; - cpu_sp <= cpu_sp + 1; - end else begin - if(BUS_RDY) cpu_pc <= cpu_pc + 1; - end - end - default: cpu_pc <= cpu_pc + 1; - endcase - end - end - OP_BUS: cpu_bus_rq <= 1'b0; - endcase - end - ST_CPU_2: begin + 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 + 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_SWP, OP_ALU, OP_MUL: 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 + if(op==OP_ALU) 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 + end + OP_ST: begin + cpu_idb <= cpu_a; + end + OP_RDRAM, OP_WRRAM: begin + if(op_imm) cpu_ramaddr <= {16'b0, op_param}; + 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 + endcase + end + ST_CPU_1: begin + CPU_STATE <= ST_CPU_2; + case(op) + OP_JP: begin + if(condtrue) begin + if(op_call) begin + cpu_stack[cpu_sp] <= cpu_pc + 1; + cpu_sp <= cpu_sp + 1; + end + cpu_pc <= op_param; + end + end + OP_SKIP: begin + if(condtrue) begin + cpu_pc <= cpu_pc + 2; + end + end + OP_RT: begin + cpu_pc <= cpu_stack[cpu_sp - 1]; + cpu_sp <= cpu_sp - 1; + end + OP_LD, OP_ST, OP_SWP, OP_RDROM, OP_RDRAM, OP_WRRAM, OP_ALU, OP_MUL, OP_BUS: + cpu_pc <= cpu_pc + 1; + OP_WAI: if(BUS_RDY) cpu_pc <= cpu_pc + 1; + default: cpu_pc <= cpu_pc + 1; + endcase + end + ST_CPU_2: begin CPU_STATE <= ST_CPU_3; - case(op) - OP_ST: begin - cx4_datram_we <= 1'b0; - end - endcase - end - ST_CPU_3: begin + 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[15:8] <= op_param; + endcase + end + OP_ST: begin + casex(op_param) + 8'h00: cpu_a <= cpu_idb; + 8'h01: cpu_acch <= cpu_idb; + 8'h02: cpu_accl <= cpu_idb; + 8'h03: cpu_busdata <= 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 + end + OP_SWP: begin + casex(op_param) + 8'h00: cpu_a <= cpu_a; + 8'h01: cpu_acch <= cpu_a; + 8'h02: cpu_accl <= cpu_a; + 8'h03: cpu_busdata <= cpu_a; + 8'h08: cpu_romdata <= cpu_a; + 8'h0c: cpu_ramdata <= cpu_a; + 8'h13: cpu_busaddr <= cpu_a; + 8'h1c: cpu_ramaddr <= cpu_a; + endcase + end + OP_RDROM: cpu_romdata <= cx4_datrom_do; + OP_RDRAM: cpu_ramdata <= cx4_datram_do; + OP_WRRAM: begin + case(cpu_op[9:8]) + 2'b00: cx4_cpu_datram_di[7:0] <= cpu_ramdata[7:0]; + 2'b01: cx4_cpu_datram_di[15:8] <= cpu_ramdata[15:8]; + 2'b10: cx4_cpu_datram_di[23:16] <= cpu_ramdata[23:16]; + endcase + cx4_cpu_datram_we <= 1'b1; + end + OP_ALU: begin + /* XXX TODO FUCK YEAH ALU */ + end + OP_BUS: cpu_bus_rq <= 1'b1; + endcase + end + ST_CPU_3: begin CPU_STATE <= ST_CPU_0; - case(op) - OP_LD, OP_SWP: begin - casex(cpu_op[15:8]) - 8'b01100x00: cpu_a <= cpu_idb; - 8'b01100x11: cpu_p <= cpu_idb; - 8'b01111100: cpu_p[7:0] <= op_param; - 8'b01111101: cpu_p[15:8] <= op_param; - 8'b01110000: cpu_romdata <= cx4_datrom_do; - 8'b01101x00: cpu_ramdata[7:0] <= cx4_datram_do; - 8'b01101x01: cpu_ramdata[15:8] <= cx4_datram_do; - 8'b01101x10: cpu_ramdata[23:16] <= cx4_datram_do; - 8'b11110000, 8'b11100000: begin - if(cpu_op[12]) cpu_a <= cpu_idb; - casex(op_param) - 8'h00: cpu_a <= cpu_a; - 8'h01: cpu_acch <= cpu_a; - 8'h02: cpu_accl <= cpu_a; - 8'h03: cpu_busdata <= cpu_a; - 8'h08: cpu_romdata <= cpu_a; - 8'h0c: cpu_ramdata <= cpu_a; - 8'h13: cpu_busaddr <= cpu_a; - 8'h1c: cpu_ramaddr <= cpu_a; - 8'h6x: {gpr[op_param[3:0]*3+2], - gpr[op_param[3:0]*3+1], - gpr[op_param[3:0]*3]} <= cpu_a; - endcase - end - endcase - end - endcase - cpu_op <= cpu_op_w; - op_param <= cpu_op_w[7:0]; - op <= &(op_id) ? OP_HLT - :(op_id[5:4] == 2'b00) ? OP_JP - :(op_id[5:2] == 4'b0110 - || op_id[5:2] == 4'b0111 - ) ? OP_LD - :(op_id[5:1] == 5'b11101) ? OP_ST - :(op_id[5:1] == 5'b01000) ? OP_BUS - :(op_id[5:3] == 3'b010 - || op_id[5:3] == 3'b100 - || op_id[5:3] == 3'b101 - || op_id[5:3] == 3'b110) ? OP_ALU - : (op_id == 6'b111100 || op_id == 6'b111000) ? OP_SWP - : OP_NOP; - op_imm <= cpu_op_w[10]; - op_sa <= cpu_op_w[9:8]; - op_p <= cpu_op_w[9]; - op_call <= cpu_op_w[13]; - cond_true <= 1'b0; - end + case(op) + OP_SWP: cpu_a <= cpu_idb; + OP_WRRAM: cx4_cpu_datram_we <= 1'b0; + OP_ALU: begin + /* XXX TODO FUCKING FLAGS */ + 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 + OP_BUS: cpu_bus_rq <= 1'b0; + endcase + cpu_op <= cpu_op_w; + 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_ALU; + 5'b01010: op <= OP_ALU; + 5'b01011: op <= OP_ALU; + 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]; + end endcase end +// gpr write, either by CPU or by MMIO +always @(posedge CLK) begin + if(CPU_STATE == ST_CPU_2 + && (op == OP_SWP) + && (op_param[7:4] == 8'h6)) begin + gpr[op_param[3:0]*3+2] <= cpu_a[23:16]; + gpr[op_param[3:0]*3+1] <= cpu_a[15:8]; + gpr[op_param[3:0]*3] <= cpu_a[7:0]; + end + else if(CPU_STATE == ST_CPU_2 + && (op == OP_ST) + && (op_param[7:4] == 8'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]] <= DI; +end /*************************** =========== MEM =========== @@ -613,7 +704,7 @@ cx4_datram cx4_datram ( .clkb(CLK), // input clkb .web(cx4_datram_we), // input [0 : 0] web .addrb(cx4_datram_addr), // input [11 : 0] addrb - .dinb(BUS_DI), // input [7 : 0] dinb + .dinb(cx4_datram_di), // input [7 : 0] dinb .doutb(cx4_datram_do) // output [7 : 0] doutb ); @@ -630,7 +721,7 @@ cx4_pgmrom cx4_pgmrom ( cx4_mul cx4_mul ( .clk(CLK), // input clk .a(cpu_a), // input [23 : 0] a - .b(cpu_mul_src), // input [23 : 0] b + .b(cpu_idb), // input [23 : 0] b .p(cpu_mul_result) // output [47 : 0] p ); endmodule