FPGA/cx4: rework CPU FSM (ALU still missing)

This commit is contained in:
ikari 2011-10-23 20:56:07 +02:00
parent e57c4aa450
commit fb9a28bf38

View File

@ -19,22 +19,22 @@
// //
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
module cx4( module cx4(
input [7:0] DI, input [7:0] DI,
output [7:0] DO, output [7:0] DO,
input [12:0] ADDR, input [12:0] ADDR,
input CS, input CS,
input nRD, input nRD,
input nWR, input nWR,
input CLK, input CLK,
input [23:0] DATROM_DI, input [23:0] DATROM_DI,
input DATROM_WE, input DATROM_WE,
input [9:0] DATROM_ADDR, input [9:0] DATROM_ADDR,
input [7:0] BUS_DI, input [7:0] BUS_DI,
output [23:0] BUS_ADDR, output [23:0] BUS_ADDR,
output BUS_RRQ, output BUS_RRQ,
input BUS_RDY, input BUS_RDY,
output cx4_active output cx4_active
); );
reg [2:0] cx4_busy; reg [2:0] cx4_busy;
parameter BUSY_CACHE = 2'b00; parameter BUSY_CACHE = 2'b00;
@ -57,10 +57,10 @@ wire [7:0] GPR_DO;
assign DO = datram_enable ? DATRAM_DO assign DO = datram_enable ? DATRAM_DO
: mmio_enable ? MMIO_DO : mmio_enable ? MMIO_DO
: status_enable ? STATUS_DO : status_enable ? STATUS_DO
: vector_enable ? VECTOR_DO : vector_enable ? VECTOR_DO
: gpr_enable ? GPR_DO : gpr_enable ? GPR_DO
: 8'h00; : 8'h00;
/* 0x1f40 - 0x1f52: MMIO /* 0x1f40 - 0x1f52: MMIO
SNES: 8 bits / CX4: various */ SNES: 8 bits / CX4: various */
@ -138,8 +138,8 @@ reg [23:0] cpu_idb; // tmp register for reg file read
/* Need to cache when: /* Need to cache when:
1f48 is written 1f48 is written
AND (selected cache page is invalid AND (selected cache page is invalid
OR selected cache page does not contain requested page already) OR selected cache page does not contain requested page already)
*/ */
reg CACHE_TRIG_ENr; reg CACHE_TRIG_ENr;
reg CACHE_TRIG_EN2r; reg CACHE_TRIG_EN2r;
@ -162,6 +162,9 @@ initial begin
end end
assign BUS_RRQ = CACHE_BUS_RRQr | DMA_BUS_RRQr; assign BUS_RRQ = CACHE_BUS_RRQr | DMA_BUS_RRQr;
reg cpu_go_en_r;
initial cpu_go_en_r = 1'b0;
initial begin initial begin
cx4_mmio_r1f50 = 8'h33; cx4_mmio_r1f50 = 8'h33;
cx4_mmio_r1f51 = 1'b0; cx4_mmio_r1f51 = 1'b0;
@ -170,74 +173,78 @@ end
always @(posedge CLK) begin always @(posedge CLK) begin
case (ADDR[4:0]) case (ADDR[4:0])
5'h00: MMIO_DOr <= cx4_mmio_dmasrc[7:0]; // 1f40 5'h00: MMIO_DOr <= cx4_mmio_dmasrc[7:0]; // 1f40
5'h01: MMIO_DOr <= cx4_mmio_dmasrc[15:8]; // 1f41 5'h01: MMIO_DOr <= cx4_mmio_dmasrc[15:8]; // 1f41
5'h02: MMIO_DOr <= cx4_mmio_dmasrc[23:16]; // 1f42 5'h02: MMIO_DOr <= cx4_mmio_dmasrc[23:16]; // 1f42
5'h03: MMIO_DOr <= cx4_mmio_dmalen[7:0]; // 1f43 5'h03: MMIO_DOr <= cx4_mmio_dmalen[7:0]; // 1f43
5'h04: MMIO_DOr <= cx4_mmio_dmalen[15:8]; // 1f44 5'h04: MMIO_DOr <= cx4_mmio_dmalen[15:8]; // 1f44
5'h05: MMIO_DOr <= cx4_mmio_dmatgt[7:0]; // 1f45 5'h05: MMIO_DOr <= cx4_mmio_dmatgt[7:0]; // 1f45
5'h06: MMIO_DOr <= cx4_mmio_dmatgt[15:8]; // 1f46 5'h06: MMIO_DOr <= cx4_mmio_dmatgt[15:8]; // 1f46
5'h07: MMIO_DOr <= cx4_mmio_dmatgt[23:16]; // 1f47 5'h07: MMIO_DOr <= cx4_mmio_dmatgt[23:16]; // 1f47
5'h08: MMIO_DOr <= {7'b0, cx4_mmio_cachepage}; 5'h08: MMIO_DOr <= {7'b0, cx4_mmio_cachepage};
5'h09: MMIO_DOr <= cx4_mmio_pgmoff[7:0]; // 1f49 5'h09: MMIO_DOr <= cx4_mmio_pgmoff[7:0]; // 1f49
5'h0a: MMIO_DOr <= cx4_mmio_pgmoff[15:8]; // 1f4a 5'h0a: MMIO_DOr <= cx4_mmio_pgmoff[15:8]; // 1f4a
5'h0b: MMIO_DOr <= cx4_mmio_pgmoff[23:16]; // 1f4b 5'h0b: MMIO_DOr <= cx4_mmio_pgmoff[23:16]; // 1f4b
5'h0c: MMIO_DOr <= {6'b0, cx4_mmio_r1f4c}; // 1f4c 5'h0c: MMIO_DOr <= {6'b0, cx4_mmio_r1f4c}; // 1f4c
5'h0d: MMIO_DOr <= cx4_mmio_pgmpage[7:0]; // 1f4d 5'h0d: MMIO_DOr <= cx4_mmio_pgmpage[7:0]; // 1f4d
5'h0e: MMIO_DOr <= {1'b0, cx4_mmio_pgmpage[14:8]}; // 1f4e 5'h0e: MMIO_DOr <= {1'b0, cx4_mmio_pgmpage[14:8]}; // 1f4e
5'h0f: MMIO_DOr <= cx4_mmio_pc; // 1f4f 5'h0f: MMIO_DOr <= cx4_mmio_pc; // 1f4f
5'h10: MMIO_DOr <= cx4_mmio_r1f50; // 1f50 5'h10: MMIO_DOr <= cx4_mmio_r1f50; // 1f50
5'h11: MMIO_DOr <= {7'b0, cx4_mmio_r1f51}; // 1f51 5'h11: MMIO_DOr <= {7'b0, cx4_mmio_r1f51}; // 1f51
5'h12: MMIO_DOr <= {7'b0, cx4_mmio_r1f52}; // 1f52 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'h13: MMIO_DOr <= cpu_mul_result[47:40]; // 1f40
// 5'h14: MMIO_DOr <= cachetag[0][15:8]; // 1f40 5'h14: MMIO_DOr <= cpu_mul_result[39:32]; // 1f40
// 5'h15: MMIO_DOr <= cachetag[0][7:0]; // 1f41 5'h15: MMIO_DOr <= cpu_mul_result[31:24]; // 1f40
// 5'h16: MMIO_DOr <= cachetag[1][15:8]; // 1f42 5'h16: MMIO_DOr <= cpu_mul_result[23:16]; // 1f40
// 5'h17: MMIO_DOr <= cachetag[1][7:0]; // 1f43 5'h17: MMIO_DOr <= cpu_mul_result[15:8]; // 1f40
default: MMIO_DOr <= 8'hff; 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 endcase
end end
always @(posedge CLK) begin always @(posedge CLK) begin
if(MMIO_WR_EN) begin if(MMIO_WR_EN) begin
case(ADDR[4:0]) case(ADDR[4:0])
5'h00: cx4_mmio_dmasrc[7:0] <= DI; // 1f40 5'h00: cx4_mmio_dmasrc[7:0] <= DI; // 1f40
5'h01: cx4_mmio_dmasrc[15:8] <= DI; // 1f41 5'h01: cx4_mmio_dmasrc[15:8] <= DI; // 1f41
5'h02: cx4_mmio_dmasrc[23:16] <= DI; // 1f42 5'h02: cx4_mmio_dmasrc[23:16] <= DI; // 1f42
5'h03: cx4_mmio_dmalen[7:0] <= DI; // 1f43 5'h03: cx4_mmio_dmalen[7:0] <= DI; // 1f43
5'h04: cx4_mmio_dmalen[15:8] <= DI; // 1f44 5'h04: cx4_mmio_dmalen[15:8] <= DI; // 1f44
5'h05: cx4_mmio_dmatgt[7:0] <= DI; // 1f45 5'h05: cx4_mmio_dmatgt[7:0] <= DI; // 1f45
5'h06: cx4_mmio_dmatgt[15:8] <= DI; // 1f46 5'h06: cx4_mmio_dmatgt[15:8] <= DI; // 1f46
5'h07: begin 5'h07: begin
cx4_mmio_dmatgt[23:16] <= DI; // 1f47 cx4_mmio_dmatgt[23:16] <= DI; // 1f47
DMA_TRIG_ENr <= 1'b1; DMA_TRIG_ENr <= 1'b1;
end end
5'h08: begin 5'h08: begin
cx4_mmio_cachepage <= DI[0]; // 1f48 cx4_mmio_cachepage <= DI[0]; // 1f48
CACHE_TRIG_ENr <= 1'b1; CACHE_TRIG_ENr <= 1'b1;
end end
5'h09: cx4_mmio_pgmoff[7:0] <= DI; // 1f49 5'h09: cx4_mmio_pgmoff[7:0] <= DI; // 1f49
5'h0a: cx4_mmio_pgmoff[15:8] <= DI; // 1f4a 5'h0a: cx4_mmio_pgmoff[15:8] <= DI; // 1f4a
5'h0b: cx4_mmio_pgmoff[23:16] <= DI; // 1f4b 5'h0b: cx4_mmio_pgmoff[23:16] <= DI; // 1f4b
5'h0c: cx4_mmio_r1f4c <= DI[1:0]; // 1f4c 5'h0c: cx4_mmio_r1f4c <= DI[1:0]; // 1f4c
5'h0d: cx4_mmio_pgmpage[7:0] <= DI; // 1f4d 5'h0d: cx4_mmio_pgmpage[7:0] <= DI; // 1f4d
5'h0e: cx4_mmio_pgmpage[14:8] <= DI[6:0]; // 1f4e 5'h0e: cx4_mmio_pgmpage[14:8] <= DI[6:0]; // 1f4e
5'h0f: cx4_mmio_pc <= DI; // 1f4f 5'h0f: begin
5'h10: cx4_mmio_r1f50 <= DI & 8'h77; // 1f50 cx4_mmio_pc <= DI; // 1f4f
5'h11: cx4_mmio_r1f51 <= DI[0]; // 1f51 cpu_go_en_r <= 1'b1;
5'h12: cx4_mmio_r1f52 <= DI[0]; // 1f52 end
endcase 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 end else begin
CACHE_TRIG_ENr <= 1'b0; CACHE_TRIG_ENr <= 1'b0;
DMA_TRIG_ENr <= 1'b0; DMA_TRIG_ENr <= 1'b0;
cpu_go_en_r <= 1'b0;
end end
end end
@ -245,10 +252,6 @@ always @(posedge CLK) begin
if(VECTOR_WR_EN) vector[ADDR[4:0]] <= DI; if(VECTOR_WR_EN) vector[ADDR[4:0]] <= DI;
end end
always @(posedge CLK) begin
if(GPR_WR_EN) gpr[ADDR[5:0]] <= DI;
end
reg [4:0] CACHE_ST; reg [4:0] CACHE_ST;
parameter ST_CACHE_IDLE = 5'b00001; parameter ST_CACHE_IDLE = 5'b00001;
parameter ST_CACHE_START = 5'b00010; 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 assign BUS_ADDR = cx4_busy[BUSY_CACHE] ? MAPPED_CACHE_SRC_ADDR
: cx4_busy[BUSY_DMA] ? MAPPED_DMA_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; reg cx4_pgmrom_we;
initial cx4_pgmrom_we = 1'b0; initial cx4_pgmrom_we = 1'b0;
@ -282,97 +285,101 @@ initial cache_count = 20'b0;
always @(posedge CLK) begin always @(posedge CLK) begin
case(CACHE_ST) case(CACHE_ST)
ST_CACHE_IDLE: begin ST_CACHE_IDLE: begin
if(CACHE_TRIG_EN if(CACHE_TRIG_EN
& (~cachetag[cx4_mmio_cachepage][15] & (~cachetag[cx4_mmio_cachepage][15]
| |(cachetag[cx4_mmio_cachepage][14:0] ^ cx4_mmio_pgmpage))) | |(cachetag[cx4_mmio_cachepage][14:0] ^ cx4_mmio_pgmpage)))
begin begin
CACHE_ST <= ST_CACHE_START; CACHE_ST <= ST_CACHE_START;
end else CACHE_ST <= ST_CACHE_IDLE; end else CACHE_ST <= ST_CACHE_IDLE;
end end
ST_CACHE_START: begin ST_CACHE_START: begin
cx4_busy[BUSY_CACHE] <= 1'b1; cx4_busy[BUSY_CACHE] <= 1'b1;
CACHE_SRC_ADDRr <= cx4_mmio_pgmoff + {cx4_mmio_pgmpage, 9'b0}; CACHE_SRC_ADDRr <= cx4_mmio_pgmoff + {cx4_mmio_pgmpage, 9'b0};
cx4_pgmrom_addr <= {cx4_mmio_cachepage, 9'b0}; cx4_pgmrom_addr <= {cx4_mmio_cachepage, 9'b0};
CACHE_ST <= ST_CACHE_WAIT; CACHE_ST <= ST_CACHE_WAIT;
cache_count <= 10'b0; cache_count <= 10'b0;
CACHE_BUS_RRQr <= 1'b1; CACHE_BUS_RRQr <= 1'b1;
end end
ST_CACHE_WAIT: begin ST_CACHE_WAIT: begin
CACHE_BUS_RRQr <= 1'b0; CACHE_BUS_RRQr <= 1'b0;
if(~CACHE_BUS_RRQr & BUS_RDY) begin if(~CACHE_BUS_RRQr & BUS_RDY) begin
CACHE_ST <= ST_CACHE_ADDR; CACHE_ST <= ST_CACHE_ADDR;
cx4_pgmrom_we <= 1'b1; cx4_pgmrom_we <= 1'b1;
cache_count <= cache_count + 1; cache_count <= cache_count + 1;
end else CACHE_ST <= ST_CACHE_WAIT; end else CACHE_ST <= ST_CACHE_WAIT;
end end
ST_CACHE_ADDR: begin ST_CACHE_ADDR: begin
cx4_pgmrom_we <= 1'b0; cx4_pgmrom_we <= 1'b0;
CACHE_SRC_ADDRr <= CACHE_SRC_ADDRr + 1; CACHE_SRC_ADDRr <= CACHE_SRC_ADDRr + 1;
cx4_pgmrom_addr <= cx4_pgmrom_addr + 1; cx4_pgmrom_addr <= cx4_pgmrom_addr + 1;
if(cache_count == 9'h1ff) begin if(cache_count == 9'h1ff) begin
cx4_busy[BUSY_CACHE] <= 1'b0; cx4_busy[BUSY_CACHE] <= 1'b0;
cachetag[cx4_mmio_cachepage] <= {1'b1,cx4_mmio_pgmpage}; cachetag[cx4_mmio_cachepage] <= {1'b1,cx4_mmio_pgmpage};
CACHE_ST <= ST_CACHE_IDLE; CACHE_ST <= ST_CACHE_IDLE;
end else begin end else begin
CACHE_BUS_RRQr <= 1'b1; CACHE_BUS_RRQr <= 1'b1;
CACHE_ST <= ST_CACHE_WAIT; CACHE_ST <= ST_CACHE_WAIT;
end end
end end
endcase endcase
end end
reg cx4_datram_we; reg cx4_dma_datram_we;
initial cx4_datram_we = 1'b0; reg cx4_cpu_datram_we;
reg [11:0] cx4_datram_addr; 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; reg [15:0] dma_count;
initial dma_count = 16'b0; initial dma_count = 16'b0;
always @(posedge CLK) begin always @(posedge CLK) begin
case(DMA_ST) case(DMA_ST)
ST_DMA_IDLE: begin ST_DMA_IDLE: begin
if(DMA_TRIG_EN) begin if(DMA_TRIG_EN) begin
DMA_ST <= ST_DMA_START; DMA_ST <= ST_DMA_START;
end else DMA_ST <= ST_DMA_IDLE; end else DMA_ST <= ST_DMA_IDLE;
end end
ST_DMA_START: begin ST_DMA_START: begin
cx4_busy[BUSY_DMA] <= 1'b1; cx4_busy[BUSY_DMA] <= 1'b1;
DMA_SRC_ADDRr <= cx4_mmio_dmasrc; DMA_SRC_ADDRr <= cx4_mmio_dmasrc;
/* XXX Rename to DMA_TGT_ADDRr and switch */ cx4_dma_datram_addr <= (cx4_mmio_dmatgt & 24'h000fff);
cx4_datram_addr <= (cx4_mmio_dmatgt & 24'h000fff); DMA_ST <= ST_DMA_WAIT;
DMA_ST <= ST_DMA_WAIT; dma_count <= cx4_mmio_dmalen;
dma_count <= cx4_mmio_dmalen;
DMA_BUS_RRQr <= 1'b1; DMA_BUS_RRQr <= 1'b1;
end end
ST_DMA_WAIT: begin ST_DMA_WAIT: begin
DMA_BUS_RRQr <= 1'b0; DMA_BUS_RRQr <= 1'b0;
if(~DMA_BUS_RRQr & BUS_RDY) begin if(~DMA_BUS_RRQr & BUS_RDY) begin
DMA_ST <= ST_DMA_ADDR; DMA_ST <= ST_DMA_ADDR;
/* XXX Rename to DMA_TGT_WEr and switch */ cx4_dma_datram_we <= 1'b1;
cx4_datram_we <= 1'b1; dma_count <= dma_count - 1;
dma_count <= dma_count - 1; end else DMA_ST <= ST_DMA_WAIT;
end else DMA_ST <= ST_DMA_WAIT; end
end ST_DMA_ADDR: begin
ST_DMA_ADDR: begin cx4_dma_datram_we <= 1'b0;
/* XXX Rename to DMA_TGT_WEr and switch */ DMA_SRC_ADDRr <= DMA_SRC_ADDRr + 1;
cx4_datram_we <= 1'b0; cx4_dma_datram_addr <= cx4_dma_datram_addr + 1;
DMA_SRC_ADDRr <= DMA_SRC_ADDRr + 1; if(dma_count == 16'h0000) begin
cx4_datram_addr <= cx4_datram_addr + 1; cx4_busy[BUSY_DMA] <= 1'b0;
if(dma_count == 16'h0000) begin DMA_ST <= ST_DMA_IDLE;
cx4_busy[BUSY_DMA] <= 1'b0; end else begin
DMA_ST <= ST_DMA_IDLE; DMA_BUS_RRQr <= 1'b1;
end else begin DMA_ST <= ST_DMA_WAIT;
DMA_BUS_RRQr <= 1'b1; end
DMA_ST <= ST_DMA_WAIT; end
end
end
endcase endcase
end end
/*************************** /***************************
=========== CPU =========== =========== CPU ===========
***************************/ ***************************/
reg [7:0] CPU_STATE; reg [4:0] CPU_STATE;
reg cpu_page; reg cpu_page;
reg [7:0] cpu_pc; reg [7:0] cpu_pc;
reg [8:0] cpu_stack [7:0]; reg [8:0] cpu_stack [7:0];
@ -396,200 +403,284 @@ reg fl_z;
reg fl_c; reg fl_c;
reg [15:0] cpu_p; 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 [23:0] cx4_datrom_do;
wire [7:0] cx4_datram_do; wire [7:0] cx4_datram_do;
parameter ST_CPU_IDLE = 8'b00000001; parameter ST_CPU_IDLE = 5'b00001;
parameter ST_CPU_0 = 8'b00000010; parameter ST_CPU_0 = 5'b00010;
parameter ST_CPU_1 = 8'b00000100; parameter ST_CPU_1 = 5'b00100;
parameter ST_CPU_2 = 8'b00001000; parameter ST_CPU_2 = 5'b01000;
parameter ST_CPU_3 = 8'b00010000; parameter ST_CPU_3 = 5'b10000;
initial CPU_STATE <= ST_CPU_IDLE; initial CPU_STATE <= ST_CPU_IDLE;
parameter OP_ALU = 4'b0000; parameter OP_NOP = 4'b0000;
parameter OP_LD = 4'b0001; parameter OP_JP = 4'b0001;
parameter OP_ST = 4'b0010; parameter OP_SKIP = 4'b0010;
parameter OP_JP = 4'b0011; parameter OP_RT = 4'b0011;
parameter OP_SWP = 4'b0100; parameter OP_LD = 4'b0100;
parameter OP_HLT = 4'b0101; parameter OP_ST = 4'b0101;
parameter OP_BUS = 4'b0110; parameter OP_SWP = 4'b0110;
parameter OP_STA = 4'b0111; parameter OP_RDROM = 4'b0111;
parameter OP_NOP = 4'b1111; 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]; wire [6:0] op_id = cpu_op_w[15:10];
reg [7:0] op_param; reg [7:0] op_param;
reg [2:0] op; reg [3:0] op;
reg [1:0] op_sa; reg [1:0] op_sa;
reg op_imm; reg op_imm;
reg op_p; reg op_p;
reg op_call; reg op_call;
reg op_jump; reg op_jump;
reg cond_true; reg condtrue;
reg cpu_go_rq;
reg cpu_bus_rq; reg cpu_bus_rq;
always @(posedge CLK) begin always @(posedge CLK) begin
case(CPU_STATE) case(CPU_STATE)
ST_CPU_IDLE: begin ST_CPU_IDLE: begin
if(cpu_go_rq) begin if(cpu_go_en_r) begin
cpu_pc <= cx4_mmio_pc; cpu_pc <= cx4_mmio_pc;
op <= OP_NOP; op <= OP_NOP;
CPU_STATE <= ST_CPU_2; CPU_STATE <= ST_CPU_2;
end cx4_busy[BUSY_CPU] <= 1'b1;
else CPU_STATE <= ST_CPU_IDLE; end
end else CPU_STATE <= ST_CPU_IDLE;
ST_CPU_0: begin // Phase 0: end
CPU_STATE <= ST_CPU_1; 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) case(op)
OP_ALU, OP_LD, OP_SWP: begin OP_JP: begin
if(cpu_op[15:10] == 6'b111000) cpu_idb <= cpu_a; // reg[imm] <- a case(cpu_op[11:10])
else if(op_imm) cpu_idb <= {16'b0, op_param}; 2'b10: condtrue <= 1'b1;
else casex(op_param) 2'b11: condtrue <= fl_z;
8'h00: cpu_idb <= cpu_a; 2'b00: condtrue <= fl_c;
8'h01: cpu_idb <= cpu_acch; 2'b01: condtrue <= fl_n;
8'h02: cpu_idb <= cpu_accl; endcase
8'h03: cpu_idb <= cpu_busdata; end
8'h08: cpu_idb <= cpu_romdata; OP_SKIP: begin
8'h0c: cpu_idb <= cpu_ramdata; case(cpu_op[9:8])
8'h13: cpu_idb <= cpu_busaddr; 2'b01: condtrue <= (fl_c == cpu_op[0]);
8'h1c: cpu_idb <= cpu_ramaddr; 2'b10: condtrue <= (fl_z == cpu_op[0]);
8'h5x: cpu_idb <= const[op_param[3:0]]; 2'b11: condtrue <= (fl_n == cpu_op[0]);
8'h6x: cpu_idb <= {gpr[op_param[3:0]*3+2], endcase
gpr[op_param[3:0]*3+1], end
gpr[op_param[3:0]*3]}; OP_LD, OP_SWP, OP_ALU, OP_MUL: begin
default: cpu_idb <= 24'b0; if(op_imm) cpu_idb <= {16'b0, op_param};
endcase else casex(op_param)
if(op==OP_ALU) begin 8'h00: cpu_idb <= cpu_a;
case(op_sa) 8'h01: cpu_idb <= cpu_acch;
2'b00: cpu_sa <= cpu_a; 8'h02: cpu_idb <= cpu_accl;
2'b01: cpu_sa <= cpu_a << 1; 8'h03: cpu_idb <= cpu_busdata;
2'b10: cpu_sa <= cpu_a << 8; 8'h08: cpu_idb <= cpu_romdata;
2'b11: cpu_sa <= cpu_a << 16; 8'h0c: cpu_idb <= cpu_ramdata;
endcase 8'h13: cpu_idb <= cpu_busaddr;
end 8'h1c: cpu_idb <= cpu_ramaddr;
end 8'h5x: cpu_idb <= const[op_param[3:0]];
OP_JP: begin 8'h6x: cpu_idb <= {gpr[op_param[3:0]*3+2],
casex(cpu_op[12:8]) gpr[op_param[3:0]*3+1],
5'b010xx: cond_true <= 1'b1; gpr[op_param[3:0]*3]};
5'b011xx: cond_true <= fl_z; default: cpu_idb <= 24'b0;
5'b100xx: cond_true <= fl_c; endcase
5'b101xx: cond_true <= fl_n; if(op==OP_ALU) begin
5'b00101: cond_true <= (fl_c == cpu_op[0]); case(op_sa)
5'b00110: cond_true <= (fl_z == cpu_op[0]); 2'b00: cpu_sa <= cpu_a;
5'b00111: cond_true <= (fl_n == cpu_op[0]); 2'b01: cpu_sa <= cpu_a << 1;
default: cond_true <= 1'b1; 2'b10: cpu_sa <= cpu_a << 8;
endcase 2'b11: cpu_sa <= cpu_a << 16;
end endcase
OP_BUS: cpu_bus_rq <= 1'b1; end
endcase end
end OP_ST: begin
ST_CPU_1: begin cpu_idb <= cpu_a;
CPU_STATE <= ST_CPU_2; end
case(op) OP_RDRAM, OP_WRRAM: begin
OP_LD: begin if(op_imm) cpu_ramaddr <= {16'b0, op_param};
cx4_datram_addr <= op_imm ? op_param : (cpu_ramaddr + cpu_idb); else casex(op_param)
cx4_datrom_addr <= cpu_a[9:0]; 8'h00: cx4_cpu_datram_addr <= cpu_a;
end 8'h01: cx4_cpu_datram_addr <= cpu_acch;
OP_ST: begin 8'h02: cx4_cpu_datram_addr <= cpu_accl;
cx4_datram_addr <= op_imm ? op_param : (cpu_ramaddr + cpu_idb); 8'h03: cx4_cpu_datram_addr <= cpu_busdata;
cx4_datram_we <= 1'b1; 8'h08: cx4_cpu_datram_addr <= cpu_romdata;
end 8'h0c: cx4_cpu_datram_addr <= cpu_ramdata;
OP_JP: begin 8'h13: cx4_cpu_datram_addr <= cpu_busaddr;
if(cond_true) begin 8'h1c: cx4_cpu_datram_addr <= cpu_ramaddr;
casex(cpu_op[12:11]) 8'h5x: cx4_cpu_datram_addr <= const[op_param[3:0]];
2'b01, 2'b10: begin 8'h6x: cx4_cpu_datram_addr <= {gpr[op_param[3:0]*3+2],
// TODO if(op_p) gpr[op_param[3:0]*3+1],
if(op_call) begin gpr[op_param[3:0]*3]};
cpu_stack[cpu_sp] <= {cpu_page, cpu_pc+1}; default: cx4_cpu_datram_addr <= 24'b0;
cpu_sp <= cpu_sp - 1; endcase
end end
cpu_pc <= op_param; endcase
end end
2'b00: begin ST_CPU_1: begin
cpu_pc <= cpu_pc + 2; CPU_STATE <= ST_CPU_2;
end case(op)
2'b11: begin OP_JP: begin
if(cpu_op[13]) begin if(condtrue) begin
{cpu_page, cpu_pc} <= cpu_stack[cpu_sp+1]; if(op_call) begin
cpu_sp <= cpu_sp + 1; cpu_stack[cpu_sp] <= cpu_pc + 1;
end else begin cpu_sp <= cpu_sp + 1;
if(BUS_RDY) cpu_pc <= cpu_pc + 1; end
end cpu_pc <= op_param;
end end
default: cpu_pc <= cpu_pc + 1; end
endcase OP_SKIP: begin
end if(condtrue) begin
end cpu_pc <= cpu_pc + 2;
OP_BUS: cpu_bus_rq <= 1'b0; end
endcase end
end OP_RT: begin
ST_CPU_2: 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; CPU_STATE <= ST_CPU_3;
case(op) case(op)
OP_ST: begin OP_LD: begin
cx4_datram_we <= 1'b0; casex(cpu_op[11:8])
end 4'b0x00: cpu_a <= cpu_idb;
endcase 4'b0x11: cpu_p <= cpu_idb;
end 4'b1100: cpu_p[7:0] <= op_param;
ST_CPU_3: begin 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; CPU_STATE <= ST_CPU_0;
case(op) case(op)
OP_LD, OP_SWP: begin OP_SWP: cpu_a <= cpu_idb;
casex(cpu_op[15:8]) OP_WRRAM: cx4_cpu_datram_we <= 1'b0;
8'b01100x00: cpu_a <= cpu_idb; OP_ALU: begin
8'b01100x11: cpu_p <= cpu_idb; /* XXX TODO FUCKING FLAGS */
8'b01111100: cpu_p[7:0] <= op_param; end
8'b01111101: cpu_p[15:8] <= op_param; OP_MUL: begin
8'b01110000: cpu_romdata <= cx4_datrom_do; cpu_acch <= cpu_mul_result[47:24];
8'b01101x00: cpu_ramdata[7:0] <= cx4_datram_do; cpu_accl <= cpu_mul_result[23:0];
8'b01101x01: cpu_ramdata[15:8] <= cx4_datram_do; fl_z <= (cpu_mul_result == 48'b0);
8'b01101x10: cpu_ramdata[23:16] <= cx4_datram_do; fl_n <= cpu_mul_result[47];
8'b11110000, 8'b11100000: begin end
if(cpu_op[12]) cpu_a <= cpu_idb; OP_BUS: cpu_bus_rq <= 1'b0;
casex(op_param) endcase
8'h00: cpu_a <= cpu_a; cpu_op <= cpu_op_w;
8'h01: cpu_acch <= cpu_a; casex(cpu_op_w[15:11])
8'h02: cpu_accl <= cpu_a; 5'b00000: op <= OP_NOP;
8'h03: cpu_busdata <= cpu_a;
8'h08: cpu_romdata <= cpu_a; 5'b00x01: op <= OP_JP;
8'h0c: cpu_ramdata <= cpu_a; 5'b00x10: op <= OP_JP;
8'h13: cpu_busaddr <= cpu_a; 5'b00100: op <= OP_SKIP;
8'h1c: cpu_ramaddr <= cpu_a; 5'b00111: op <= OP_RT;
8'h6x: {gpr[op_param[3:0]*3+2],
gpr[op_param[3:0]*3+1], 5'b01100: op <= OP_LD;
gpr[op_param[3:0]*3]} <= cpu_a; 5'b01111: op <= OP_LD;
endcase 5'b11100: op <= OP_ST;
end 5'b11110: op <= OP_SWP;
endcase
end 5'b01110: op <= OP_RDROM;
endcase 5'b01101: op <= OP_RDRAM;
cpu_op <= cpu_op_w; 5'b11101: op <= OP_WRRAM;
op_param <= cpu_op_w[7:0];
op <= &(op_id) ? OP_HLT 5'b01001: op <= OP_ALU;
:(op_id[5:4] == 2'b00) ? OP_JP 5'b01010: op <= OP_ALU;
:(op_id[5:2] == 4'b0110 5'b01011: op <= OP_ALU;
|| op_id[5:2] == 4'b0111 5'b10000: op <= OP_ALU;
) ? OP_LD 5'b10001: op <= OP_ALU;
:(op_id[5:1] == 5'b11101) ? OP_ST 5'b10010: op <= OP_ALU;
:(op_id[5:1] == 5'b01000) ? OP_BUS 5'b10101: op <= OP_ALU;
:(op_id[5:3] == 3'b010 5'b10110: op <= OP_ALU;
|| op_id[5:3] == 3'b100 5'b10111: op <= OP_ALU;
|| op_id[5:3] == 3'b101 5'b11000: op <= OP_ALU;
|| op_id[5:3] == 3'b110) ? OP_ALU 5'b11001: op <= OP_ALU;
: (op_id == 6'b111100 || op_id == 6'b111000) ? OP_SWP 5'b11010: op <= OP_ALU;
: OP_NOP; 5'b11011: op <= OP_ALU;
op_imm <= cpu_op_w[10]; 5'b10011: op <= OP_MUL;
op_sa <= cpu_op_w[9:8];
op_p <= cpu_op_w[9]; 5'b00011: op <= OP_WAI;
op_call <= cpu_op_w[13]; 5'b01000: op <= OP_BUS;
cond_true <= 1'b0;
end 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 endcase
end 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 =========== =========== MEM ===========
@ -613,7 +704,7 @@ cx4_datram cx4_datram (
.clkb(CLK), // input clkb .clkb(CLK), // input clkb
.web(cx4_datram_we), // input [0 : 0] web .web(cx4_datram_we), // input [0 : 0] web
.addrb(cx4_datram_addr), // input [11 : 0] addrb .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 .doutb(cx4_datram_do) // output [7 : 0] doutb
); );
@ -630,7 +721,7 @@ cx4_pgmrom cx4_pgmrom (
cx4_mul cx4_mul ( cx4_mul cx4_mul (
.clk(CLK), // input clk .clk(CLK), // input clk
.a(cpu_a), // input [23 : 0] a .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 .p(cpu_mul_result) // output [47 : 0] p
); );
endmodule endmodule