FPGA/cx4: rework CPU FSM (ALU still missing)
This commit is contained in:
parent
e57c4aa450
commit
fb9a28bf38
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user