hp-saturn/saturn_core.v

916 lines
18 KiB
Coq
Raw Normal View History

2019-02-04 15:02:33 +01:00
/**************************************************************************************************
*
*
*
*
*
*/
2019-02-04 09:59:35 +01:00
module hp_rom (
2019-02-04 10:38:42 +01:00
input clk,
2019-02-04 09:59:35 +01:00
input [19:0] address,
2019-02-04 10:38:42 +01:00
input enable,
output reg [3:0] nibble_out
2019-02-04 09:59:35 +01:00
);
2019-02-04 10:38:42 +01:00
localparam ROM_FILENAME = "rom-gx-r.hex";
2019-02-04 09:59:35 +01:00
2019-02-04 15:30:18 +01:00
reg [3:0] rom [0:(2**20)-1];
//reg[3:0] rom [0:(2**16)-1];
2019-02-04 09:59:35 +01:00
initial
begin
if ( ROM_FILENAME != "" )
$readmemh( ROM_FILENAME, rom);
end
2019-02-04 10:38:42 +01:00
always @(posedge clk)
if (enable)
nibble_out <= rom[address];
2019-02-04 09:59:35 +01:00
endmodule
2019-02-04 15:02:33 +01:00
/**************************************************************************************************
*
*
*
*
*
*/
2019-02-04 09:59:35 +01:00
module saturn_core (
2019-02-04 15:02:33 +01:00
input clk,
input reset,
output halt,
output [3:0] runstate,
output [31:0] decstate
2019-02-04 09:59:35 +01:00
);
2019-02-04 15:02:33 +01:00
localparam RUN_START = 0;
localparam READ_ROM_STA = 1;
localparam READ_ROM_CLK = 2;
localparam READ_ROM_STR = 3;
localparam READ_ROM_VAL = 4;
2019-02-04 15:30:18 +01:00
localparam RUN_EXEC = 14;
2019-02-04 15:02:33 +01:00
localparam RUN_DECODE = 15;
2019-02-04 09:59:35 +01:00
// decoder stuff
2019-02-04 10:38:42 +01:00
localparam DECODE_START = 32'h00000000;
2019-02-04 09:59:35 +01:00
2019-02-04 10:55:17 +01:00
localparam DECODE_0 = 32'h00000001;
2019-02-04 10:38:42 +01:00
localparam DECODE_0X = 32'h00000002;
2019-02-04 09:59:35 +01:00
2019-02-04 10:55:17 +01:00
localparam DECODE_1 = 32'h00000010;
2019-02-04 10:38:42 +01:00
localparam DECODE_1X = 32'h00000011;
2019-02-04 15:02:33 +01:00
localparam DECODE_14 = 32'h00000410;
localparam DECODE_15 = 32'h00000510;
localparam DECODE_MEMACCESS = 32'h00000411;
2019-02-04 10:38:42 +01:00
localparam DECODE_D0_EQ_5N = 32'h00000b10;
2019-02-04 09:59:35 +01:00
2019-02-04 10:55:17 +01:00
localparam DECODE_P_EQ = 32'h00000020;
2019-02-04 09:59:35 +01:00
2019-02-04 10:55:17 +01:00
localparam DECODE_LC_LEN = 32'h00000030;
localparam DECODE_LC = 32'h00000031;
2019-02-04 09:59:35 +01:00
2019-02-04 10:55:17 +01:00
localparam DECODE_GOTO = 32'h00000060;
2019-02-04 09:59:35 +01:00
2019-02-04 10:55:17 +01:00
localparam DECODE_8 = 32'h00000080;
2019-02-04 10:38:42 +01:00
localparam DECODE_8X = 32'h00000081;
localparam DECODE_80 = 32'h00000082;
2019-02-04 09:59:35 +01:00
2019-02-04 10:38:42 +01:00
localparam DECODE_RESET = 32'h0000A080;
2019-02-04 09:59:35 +01:00
2019-02-04 10:55:17 +01:00
localparam DECODE_C_EQ_P_N = 32'h0000C080;
2019-02-04 09:59:35 +01:00
2019-02-04 10:38:42 +01:00
localparam DECODE_82 = 32'h00000280;
2019-02-04 09:59:35 +01:00
2019-02-04 10:55:17 +01:00
localparam DECODE_ST_EQ_0_N = 32'h00000480;
localparam DECODE_ST_EQ_1_N = 32'h00000580;
2019-02-04 09:59:35 +01:00
2019-02-04 10:55:17 +01:00
localparam DECODE_GOVLNG = 32'h00000d80;
localparam DECODE_GOSBVL = 32'h00000f80;
2019-02-04 09:59:35 +01:00
2019-02-04 15:02:33 +01:00
localparam DECODE_A = 32'h000000a0;
localparam DECODE_A_FS = 32'h000000a1;
2019-02-04 10:38:42 +01:00
localparam HEX = 0;
localparam DEC = 1;
2019-02-04 09:59:35 +01:00
// state machine stuff
2019-02-04 15:02:33 +01:00
reg halt;
reg [3:0] runstate;
reg [31:0] decstate;
2019-02-04 09:59:35 +01:00
// memory access
2019-02-04 15:02:33 +01:00
reg rom_clock;
2019-02-04 09:59:35 +01:00
reg [19:0] rom_address;
2019-02-04 15:02:33 +01:00
reg rom_enable;
wire[3:0] rom_nibble;
2019-02-04 09:59:35 +01:00
// internal registers
2019-02-04 15:02:33 +01:00
reg [3:0] nibble;
2019-02-04 09:59:35 +01:00
reg [19:0] saved_PC;
reg [2:0] rstk_ptr;
reg [19:0] jump_base;
reg [19:0] jump_offset;
2019-02-04 15:02:33 +01:00
reg hex_dec;
2019-02-04 09:59:35 +01:00
reg [3:0] load_cnt;
reg [3:0] load_ctr;
2019-02-04 15:02:33 +01:00
reg [3:0] tmp_field;
2019-02-04 09:59:35 +01:00
// processor registers
reg [19:0] PC;
reg [3:0] P;
reg [15:0] ST;
reg [3:0] HST;
2019-02-04 15:02:33 +01:00
reg Carry;
2019-02-04 09:59:35 +01:00
reg [19:0] RSTK[0:7];
reg [19:0] D0;
reg [19:0] D1;
reg [63:0] A;
reg [63:0] B;
reg [63:0] C;
reg [63:0] D;
reg [63:0] R0;
reg [63:0] R1;
reg [63:0] R2;
reg [63:0] R3;
reg [63:0] R4;
hp_rom calc_rom (
.clk (clk),
.address (rom_address),
.enable (rom_enable),
.nibble_out (rom_nibble)
);
always @(posedge clk)
if (reset)
2019-02-04 15:02:33 +01:00
begin
hex_dec <= HEX;
rstk_ptr <= 7;
PC <= 0;
P <= 0;
ST <= 0;
HST <= 0;
Carry <= 0;
RSTK[0] <= 0;
RSTK[1] <= 0;
RSTK[2] <= 0;
RSTK[3] <= 0;
RSTK[4] <= 0;
RSTK[5] <= 0;
RSTK[6] <= 0;
RSTK[7] <= 0;
D0 <= 0;
D1 <= 0;
A <= 0;
B <= 0;
C <= 0;
D <= 0;
R0 <= 0;
R1 <= 0;
R2 <= 0;
R3 <= 0;
R4 <= 0;
halt <= 0;
runstate <= RUN_START;
decstate <= DECODE_START;
end
2019-02-04 09:59:35 +01:00
else
2019-02-04 15:02:33 +01:00
if (runstate == RUN_START)
runstate <= READ_ROM_STA;
2019-02-04 09:59:35 +01:00
//--------------------------------------------------------------------------------------------------
//
// REGISTER UTILITIES
//
//--------------------------------------------------------------------------------------------------
2019-02-04 15:02:33 +01:00
// display registers
`ifdef SIM
2019-02-04 15:02:33 +01:00
always @(posedge clk)
if ((runstate == RUN_START) & (~reset))
begin
saved_PC <= PC;
$display("PC: %05h Carry: %b h: %s rp: %h RSTK7: %05h", PC, Carry, hex_dec?"DEC":"HEX", rstk_ptr, RSTK[7]);
$display("P: %h HST: %b ST: %b RSTK6: %5h", P, HST, ST, RSTK[6]);
$display("A: %h R0: %h RSTK5: %5h", A, R0, RSTK[5]);
$display("B: %h R1: %h RSTK4: %5h", B, R1, RSTK[4]);
$display("C: %h R2: %h RSTK3: %5h", C, R2, RSTK[3]);
$display("D: %h R3: %h RSTK2: %5h", D, R3, RSTK[2]);
$display("D0: %h D1: %h R4: %h RSTK1: %5h", D0, D1, R4, RSTK[1]);
$display(" RSTK0: %5h", RSTK[0]);
end
`endif
2019-02-04 09:59:35 +01:00
//--------------------------------------------------------------------------------------------------
//
// ROM HANDLING
//
//--------------------------------------------------------------------------------------------------
2019-02-04 15:02:33 +01:00
// read from rom start
always @(posedge clk)
if (runstate == READ_ROM_STA)
begin
//$display("READ_ROM_STA");
rom_enable <= 1'b1;
rom_address <= PC;
runstate <= READ_ROM_CLK;
end
// read from rom clock in
always @(posedge clk)
if (runstate == READ_ROM_CLK)
begin
//$display("READ_ROM_CLK");
rom_clock <= 1'b1;
runstate <= READ_ROM_STR;
end
// read from rom store
always @(posedge clk)
if (runstate == READ_ROM_STR)
begin
//$display("READ_ROM_STR");
nibble <= rom_nibble;
//$display("PC: %h | read => %h", PC, rom_nibble);
PC <= PC + 1;
rom_enable <= 1'b0;
rom_clock <= 1'b0;
runstate <= READ_ROM_VAL;
end
2019-02-04 09:59:35 +01:00
//--------------------------------------------------------------------------------------------------
//
// INSTRUCTION DECODING
//
//--------------------------------------------------------------------------------------------------
2019-02-04 15:02:33 +01:00
// first nibble instruction decoder
always @(posedge clk)
if ((runstate == READ_ROM_VAL) & (decstate == DECODE_START))
begin
//$display("READ_ROM_VAL -> instruction decoder");
runstate <= RUN_DECODE;
case (nibble)
//4'h0 : decstate <= DECODE_0;
//4'h1 : decstate <= DECODE_1;
4'h2 : decstate <= DECODE_P_EQ;
//4'h3 : decstate <= DECODE_LC;
2019-02-04 15:30:18 +01:00
4'h6 : decstate <= DECODE_GOTO;
2019-02-04 15:48:06 +01:00
4'h8 : decstate <= DECODE_8;
2019-02-04 15:02:33 +01:00
//4'ha : decstate <= DECODE_A_FS;
default:
begin
`ifdef SIM
2019-02-04 15:02:33 +01:00
$display("%05h nibble %h => unimplemented", saved_PC, nibble);
`endif
2019-02-04 15:02:33 +01:00
halt <= 1;
end
endcase
end
/*
2019-02-04 09:59:35 +01:00
task instruction_decoder_unhandled;
begin
2019-02-04 15:02:33 +01:00
$display("unhandled state %h last nibble %h", decstate , nibble);
2019-02-04 09:59:35 +01:00
halt_processor();
end
endtask
task instruction_decoder;
2019-02-04 15:02:33 +01:00
case (decstate )
2019-02-04 09:59:35 +01:00
DECODE_START: instruction_decoder_start();
// instruction specific stuff
DECODE_0, DECODE_0X: decode_0();
DECODE_1, DECODE_1X: decode_1();
2019-02-04 15:02:33 +01:00
DECODE_14, DECODE_15: decode_14_15();
2019-02-04 10:38:42 +01:00
DECODE_D0_EQ_5N: inst_d0_eq_5n();
2019-02-04 10:55:17 +01:00
DECODE_P_EQ: inst_p_equals();
DECODE_LC_LEN, DECODE_LC: inst_lc();
2019-02-04 10:38:42 +01:00
DECODE_GOTO: inst_goto();
2019-02-04 10:55:17 +01:00
DECODE_8, DECODE_8X: decode_8();
2019-02-04 10:38:42 +01:00
DECODE_80: decode_80();
2019-02-04 10:55:17 +01:00
DECODE_C_EQ_P_N: inst_c_eq_p_n();
2019-02-04 10:38:42 +01:00
DECODE_82: decode_82();
2019-02-04 10:55:17 +01:00
DECODE_ST_EQ_0_N: inst_st_eq_0_n();
DECODE_ST_EQ_1_N: inst_st_eq_1_n();
2019-02-04 10:38:42 +01:00
DECODE_GOVLNG, DECODE_GOSBVL: inst_govlng_gosbvl();
2019-02-04 15:02:33 +01:00
DECODE_A: decode_a();
DECODE_A_FS: decode_a_fs();
2019-02-04 09:59:35 +01:00
default: instruction_decoder_unhandled();
endcase
endtask
task halt_processor;
begin
halt <= 1;
end
endtask
task end_decode;
begin
read_state <= READ_START;
run_state <= RUN_START;
2019-02-04 15:02:33 +01:00
decstate <= DECODE_START;
2019-02-04 09:59:35 +01:00
end
endtask
task decode_0;
2019-02-04 15:02:33 +01:00
case (decstate )
2019-02-04 09:59:35 +01:00
DECODE_START:
begin
2019-02-04 15:02:33 +01:00
decstate <= DECODE_0X;
2019-02-04 09:59:35 +01:00
read_state <= READ_START;
end
DECODE_0X:
if (read_state != READ_VALID) read_rom();
else decode_0x();
endcase
endtask
task decode_0x;
2019-02-04 15:02:33 +01:00
case (nibble)
2019-02-04 09:59:35 +01:00
4'h3: inst_rtncc();
4'h4: inst_sethex();
default: instruction_decoder_unhandled();
endcase
endtask
// 03 RTNCC
task inst_rtncc;
begin
Carry = 0;
PC = RSTK[rstk_ptr];
RSTK[rstk_ptr] = 0;
rstk_ptr = rstk_ptr - 1;
$display("%05h RTNCC", saved_PC);
end_decode();
end
endtask
// 04 SETHEX
task inst_sethex;
begin
hex_dec = HEX;
$display("%05h SETHEX", saved_PC);
end_decode();
end
endtask
task decode_1;
2019-02-04 15:02:33 +01:00
case (decstate )
2019-02-04 09:59:35 +01:00
DECODE_START:
begin
2019-02-04 15:02:33 +01:00
decstate = DECODE_1X;
2019-02-04 09:59:35 +01:00
read_state = READ_START;
end
DECODE_1X:
if (read_state != READ_VALID) read_rom();
else decode_1x();
endcase
endtask
task decode_1x;
2019-02-04 15:02:33 +01:00
case (nibble)
4'h4, 4'h5: decode_14_15();
4'hb: inst_d0_eq_5n();
default: instruction_decoder_unhandled();
2019-02-04 09:59:35 +01:00
endcase
endtask
2019-02-04 15:02:33 +01:00
task decode_14_15;
case (decstate)
DECODE_1X:
begin
read_state <= READ_START;
case (nibble)
4'h4: decstate <= DECODE_14;
4'h5: decstate <= DECODE_15;
endcase
end
DECODE_14, DECODE_15:
if (read_state != READ_VALID) read_rom();
else
case (nibble)
default:
begin
$display("memacess %h %h", decstate[11:8], nibble);
halt_processor();
end
endcase
endcase
endtask
2019-02-04 09:59:35 +01:00
// 1bnnnnn DO=(5) nnnnn
task inst_d0_eq_5n;
2019-02-04 15:02:33 +01:00
case (decstate )
2019-02-04 09:59:35 +01:00
DECODE_1X:
begin
2019-02-04 15:02:33 +01:00
decstate = DECODE_D0_EQ_5N;
2019-02-04 09:59:35 +01:00
read_state = READ_START;
load_cnt = 4;
load_ctr = 0;
$write("%5h D0=(5)\t", saved_PC);
end
DECODE_D0_EQ_5N:
if (read_state != READ_VALID) read_rom();
else
begin
2019-02-04 15:02:33 +01:00
D0[load_ctr*4+:4] = nibble;
$write("%1h", nibble);
2019-02-04 09:59:35 +01:00
if (load_ctr == load_cnt)
begin
$display("");
end_decode();
end
else
begin
load_ctr = load_ctr + 1;
read_state = READ_START;
end
end
endcase
endtask
2019-02-04 15:02:33 +01:00
*/
2019-02-04 09:59:35 +01:00
2019-02-04 15:30:18 +01:00
/******************************************************************************
* 2n P= n
*
*
*/
2019-02-04 15:02:33 +01:00
always @(posedge clk)
if (decstate == DECODE_P_EQ)
case (runstate)
2019-02-04 15:48:06 +01:00
RUN_DECODE: runstate <= READ_ROM_STA;
2019-02-04 15:02:33 +01:00
READ_ROM_STA, READ_ROM_CLK, READ_ROM_STR: ;
READ_ROM_VAL:
begin
P <= nibble;
`ifdef SIM
2019-02-04 15:02:33 +01:00
$display("%05h P=\t%h", saved_PC, nibble);
`endif
2019-02-04 15:02:33 +01:00
runstate <= RUN_START;
decstate <= DECODE_START;
end
default:
begin
`ifdef SIM
2019-02-04 15:02:33 +01:00
$display("runstate %h", runstate);
`endif
2019-02-04 15:02:33 +01:00
halt <= 1;
end
endcase
/*
2019-02-04 09:59:35 +01:00
// 3nxxxxxxxxxxxxxxxx LC xxxxxxxxxxxxxxxx
task inst_lc;
2019-02-04 15:02:33 +01:00
case (decstate )
2019-02-04 09:59:35 +01:00
DECODE_START:
begin
2019-02-04 15:02:33 +01:00
decstate = DECODE_LC_LEN;
2019-02-04 09:59:35 +01:00
read_state = READ_START;
end
DECODE_LC_LEN:
if (read_state != READ_VALID) read_rom();
else
begin
2019-02-04 15:02:33 +01:00
load_cnt = nibble;
2019-02-04 09:59:35 +01:00
load_ctr = 0;
2019-02-04 15:02:33 +01:00
decstate = DECODE_LC;
2019-02-04 09:59:35 +01:00
read_state = READ_START;
$write("%5h LC (%h)\t", saved_PC, load_cnt);
end
2019-02-04 10:55:17 +01:00
DECODE_LC:
2019-02-04 09:59:35 +01:00
if (read_state != READ_VALID) read_rom();
else
begin
2019-02-04 15:02:33 +01:00
C[((load_ctr+P)%16)*4+:4] = nibble;
$write("%1h", nibble);
2019-02-04 09:59:35 +01:00
if (load_ctr == load_cnt)
begin
$display("");
end_decode();
end
else
begin
load_ctr = (load_ctr + 1)%4'hf;
read_state = READ_START;
end
end
endcase
endtask
2019-02-04 15:30:18 +01:00
*/
2019-02-04 09:59:35 +01:00
2019-02-04 15:30:18 +01:00
/******************************************************************************
* 6zyx GOTO xyz
*
*
*/
always @(posedge clk)
if (decstate == DECODE_GOTO)
case (runstate)
RUN_DECODE:
2019-02-04 09:59:35 +01:00
begin
2019-02-04 15:30:18 +01:00
runstate <= READ_ROM_STA;
jump_base <= PC;
jump_offset <= 0;
load_cnt <= 2;
load_ctr <= 0;
`ifdef SIM
2019-02-04 15:30:18 +01:00
$write("%5h GOTO\t", saved_PC);
`endif
2019-02-04 15:30:18 +01:00
end
READ_ROM_STA, READ_ROM_CLK, READ_ROM_STR: ;
READ_ROM_VAL:
begin
jump_offset[load_ctr*4+:4] <= nibble;
`ifdef SIM
2019-02-04 15:02:33 +01:00
$write("%1h", nibble);
`endif
2019-02-04 15:30:18 +01:00
if (load_ctr == load_cnt) runstate <= RUN_EXEC;
2019-02-04 10:55:17 +01:00
else
begin
2019-02-04 15:30:18 +01:00
load_ctr <= load_ctr + 1;
runstate <= READ_ROM_STA;
2019-02-04 10:55:17 +01:00
end
2019-02-04 09:59:35 +01:00
end
2019-02-04 15:30:18 +01:00
RUN_EXEC:
begin
`ifdef SIM
2019-02-04 15:30:18 +01:00
$display("\t=> %05h", jump_base + jump_offset);
`endif PC <= jump_base + jump_offset;
2019-02-04 15:30:18 +01:00
runstate <= RUN_START;
decstate <= DECODE_START;
end
default:
begin
`ifdef SIM
2019-02-04 15:30:18 +01:00
$display("runstate %h", runstate);
`endif
2019-02-04 15:30:18 +01:00
halt <= 1;
end
endcase
2019-02-04 15:48:06 +01:00
/******************************************************************************
* 8
* a lot of things start with 8...
*
*/
2019-02-04 15:30:18 +01:00
2019-02-04 15:48:06 +01:00
always @(posedge clk)
if (decstate == DECODE_8)
case (runstate)
RUN_DECODE: runstate <= READ_ROM_STA;
READ_ROM_STA, READ_ROM_CLK, READ_ROM_STR: ;
READ_ROM_VAL:
begin
case (nibble)
//4'h0: decode_80();
//4'h2: decode_82();
//4'h4: inst_st_eq_0_n();
//4'h5: inst_st_eq_1_n();
4'hd: decstate <= DECODE_GOVLNG;
//4'hf: decstate <= DECODE_GOSBVL;
default:
begin
`ifdef SIM
$display("unhandled instruction prefix 8%h", nibble);
`endif
halt <= 1;
end
endcase
runstate <= RUN_DECODE;
end
2019-02-04 15:48:06 +01:00
default:
begin
`ifdef SIM
2019-02-04 15:48:06 +01:00
$display("runstate %h", runstate);
`endif
2019-02-04 15:48:06 +01:00
halt <= 1;
end
endcase
2019-02-04 15:30:18 +01:00
/*
2019-02-04 09:59:35 +01:00
task decode_80;
2019-02-04 15:02:33 +01:00
case (decstate )
2019-02-04 09:59:35 +01:00
DECODE_8X:
begin
2019-02-04 15:02:33 +01:00
decstate <= DECODE_80;
2019-02-04 09:59:35 +01:00
read_state <= READ_START;
end
DECODE_80:
if (read_state != READ_VALID) read_rom();
else
2019-02-04 15:02:33 +01:00
case (nibble)
2019-02-04 09:59:35 +01:00
4'h5: inst_config();
4'ha: inst_reset();
2019-02-04 10:55:17 +01:00
4'hc: inst_c_eq_p_n();
2019-02-04 09:59:35 +01:00
default:
begin
2019-02-04 15:02:33 +01:00
$display("decode_80: %h", nibble);
2019-02-04 09:59:35 +01:00
halt_processor();
end
endcase
endcase
endtask
// 805 CONFIG
task inst_config;
begin
$display("%05h CONFIG\t\t\t<= NOT IMPLEMENTED YET", saved_PC);
end_decode();
end
endtask
// 80A RESET
task inst_reset;
begin
$display("%05h RESET\t\t\t<= NOT IMPLEMENTED YET", saved_PC);
end_decode();
end
endtask
// 80Cn C=P n
2019-02-04 10:55:17 +01:00
task inst_c_eq_p_n;
2019-02-04 15:02:33 +01:00
case (decstate )
2019-02-04 09:59:35 +01:00
DECODE_80:
begin
2019-02-04 15:02:33 +01:00
decstate <= DECODE_C_EQ_P_N;
2019-02-04 09:59:35 +01:00
read_state <= READ_START;
end
2019-02-04 10:55:17 +01:00
DECODE_C_EQ_P_N:
2019-02-04 09:59:35 +01:00
if (read_state != READ_VALID) read_rom();
else
begin
2019-02-04 15:02:33 +01:00
$display("%05h C=P\t%h", saved_PC, nibble);
C[nibble*4+:4] <= P;
2019-02-04 09:59:35 +01:00
end_decode();
end
endcase
endtask
task decode_82;
2019-02-04 15:02:33 +01:00
case (decstate )
2019-02-04 09:59:35 +01:00
DECODE_8X:
begin
2019-02-04 15:02:33 +01:00
decstate <= DECODE_82;
2019-02-04 09:59:35 +01:00
read_state <= READ_START;
end
DECODE_82:
if (read_state != READ_VALID) read_rom();
else
begin
2019-02-04 15:02:33 +01:00
HST <= HST & ~nibble;
case (nibble)
2019-02-04 09:59:35 +01:00
4'h1: $display("%5h XM=0", saved_PC);
4'h2: $display("%5h SB=0", saved_PC);
4'h4: $display("%5h SR=0", saved_PC);
4'h8: $display("%5h MP=0", saved_PC);
4'hf: $display("%5h CLRHST", saved_PC);
2019-02-04 15:02:33 +01:00
default: $display("%5h CLRHST %f", saved_PC, nibble);
2019-02-04 09:59:35 +01:00
endcase
end_decode();
end
endcase
endtask
*/
2019-02-04 09:59:35 +01:00
/******************************************************************************
* ---------- field -----------
* A B fs d
* ----------------------------
* 140 148 150a 158x DAT0=A field
* 141 149 151a 159x DAT1=A field
* 142 14A 152a 15Ax A=DAT0 field
* 143 14B 153a 15Bx A=DAT1 field
* 144 14C 154a 15Cx DAT0=C field
* 145 14D 155a 15Dx DAT1=C field
* 146 14E 156a 15Ex C=DAT0 field
* 147 14F 157a 15Fx C=DAT1 field
*
* fs: P WP XS X S M B W
* a: 0 1 2 3 4 5 6 7
*
* x = d - 1 x = n - 1
*/
/*
2019-02-04 09:59:35 +01:00
// 84n ST=0 n
2019-02-04 10:55:17 +01:00
task inst_st_eq_0_n;
2019-02-04 15:02:33 +01:00
case (decstate )
2019-02-04 09:59:35 +01:00
DECODE_8X:
begin
2019-02-04 15:02:33 +01:00
decstate <= DECODE_ST_EQ_0_N;
2019-02-04 09:59:35 +01:00
read_state <= READ_START;
end
2019-02-04 10:55:17 +01:00
DECODE_ST_EQ_0_N:
2019-02-04 09:59:35 +01:00
if (read_state != READ_VALID) read_rom();
else
begin
2019-02-04 15:02:33 +01:00
$display("%05h ST=0\t%h", saved_PC, nibble);
ST[nibble] <= 0;
2019-02-04 09:59:35 +01:00
end_decode();
end
endcase
endtask
// 85n ST=1 n
2019-02-04 10:55:17 +01:00
task inst_st_eq_1_n;
2019-02-04 15:02:33 +01:00
case (decstate )
2019-02-04 09:59:35 +01:00
DECODE_8X:
begin
2019-02-04 15:02:33 +01:00
decstate <= DECODE_ST_EQ_1_N;
2019-02-04 09:59:35 +01:00
read_state <= READ_START;
end
2019-02-04 10:55:17 +01:00
DECODE_ST_EQ_1_N:
2019-02-04 09:59:35 +01:00
if (read_state != READ_VALID) read_rom();
else
begin
2019-02-04 15:02:33 +01:00
$display("%05h ST=1\t%h", saved_PC, nibble);
ST[nibble] <= 1;
2019-02-04 09:59:35 +01:00
end_decode();
end
endcase
endtask
2019-02-04 15:48:06 +01:00
*/
2019-02-04 09:59:35 +01:00
2019-02-04 15:48:06 +01:00
/******************************************************************************
* 8Dzyxwv GOVLNG vwxyz
* 8Fzyxwv GOSBVL vwxyz
* two for the price of one...
*/
always @(posedge clk)
if ((decstate == DECODE_GOVLNG) | (decstate == DECODE_GOSBVL))
case (runstate)
RUN_DECODE:
2019-02-04 09:59:35 +01:00
begin
jump_base <= 0;
load_cnt <= 4;
load_ctr <= 0;
`ifdef SIM
case (decstate)
DECODE_GOVLNG: $write("%5h GOVLNG\t", saved_PC);
DECODE_GOSBVL: $write("%5h GOSBVL\t", saved_PC);
endcase
`endif
if (decstate == DECODE_GOSBVL)
rstk_ptr <= rstk_ptr + 1;
runstate <= READ_ROM_STA;
end
READ_ROM_STA, READ_ROM_CLK, READ_ROM_STR: ;
READ_ROM_VAL:
begin
//$display("decstate %h | nibble %h", decstate, nibble);
jump_base[load_ctr*4+:4] = nibble;
`ifdef SIM
$write("%1h", nibble);
`endif
if (load_ctr == load_cnt) runstate <= RUN_EXEC;
2019-02-04 10:38:42 +01:00
else
begin
load_ctr <= load_ctr + 1;
runstate <= READ_ROM_STA;
2019-02-04 10:38:42 +01:00
end
2019-02-04 09:59:35 +01:00
end
RUN_EXEC:
begin
`ifdef SIM
$display("\t=> %5h", jump_base);
`endif
if (decstate == DECODE_GOSBVL)
RSTK[rstk_ptr] <= PC;
PC <= jump_base;
runstate <= RUN_START;
decstate <= DECODE_START;
end
default:
begin
`ifdef SIM
$display("decstate %h", decstate);
`endif
halt <= 1;
end
endcase
2019-02-04 09:59:35 +01:00
/*
2019-02-04 15:02:33 +01:00
task decode_a;
case (decstate)
DECODE_START:
begin
decstate <= DECODE_A;
read_state <= READ_START;
end
DECODE_A:
if (read_state != READ_VALID) read_rom();
else
begin
tmp_field <= nibble;
decstate <= DECODE_A_FS;
read_state <= READ_START;
end
endcase
endtask
task decode_a_fs;
case (decstate)
DECODE_A_FS:
if (read_state != READ_VALID) read_rom();
else
begin
$write("%5h ", saved_PC);
case (tmp_field)
4'h0, 4'h1, 4'h2, 4'h3, 4'h4, 4'h5, 4'h6, 4'h7:
begin
$display("a%h%h", tmp_field, nibble);
halt_processor();
end
4'h8, 4'h9, 4'ha, 4'hb, 4'hc, 4'hd, 4'he, 4'hf:
begin
case (nibble)
4'h2: // C=0 fs
begin
$write("C=0\t");
case (tmp_field)
4'he: C[7:0] <= 0;
default:
begin
$display("a%h%h", tmp_field, nibble);
halt_processor();
end
endcase
end
default:
begin
$display("a%h%h", tmp_field, nibble);
halt_processor();
end
endcase
case (tmp_field)
4'he: $display("B");
endcase
if (~halt)
end_decode();
end
endcase
end
endcase
endtask
*/
2019-02-04 09:59:35 +01:00
endmodule
`ifdef SIM
module rom_tb;
2019-02-04 15:02:33 +01:00
reg clk;
reg reset;
2019-02-04 09:59:35 +01:00
wire halt;
2019-02-04 15:02:33 +01:00
wire [3:0] runstate;
wire [31:0] decstate;
2019-02-04 09:59:35 +01:00
saturn_core saturn (
2019-02-04 15:02:33 +01:00
.clk (clk),
.reset (reset),
.halt (halt),
.runstate (runstate),
.decstate (decstate)
2019-02-04 09:59:35 +01:00
);
always
#10 clk = (clk === 1'b0);
initial begin
2019-02-04 15:02:33 +01:00
//$monitor ("c %b | r %b | run %h | dec %h", clk, reset, runstate, decstate);
2019-02-04 09:59:35 +01:00
end
initial begin
2019-02-04 15:02:33 +01:00
$display("starting the simulation");
2019-02-04 09:59:35 +01:00
clk <= 0;
reset <= 1;
@(posedge clk);
reset <= 0;
@(posedge halt);
$finish;
end
endmodule
`endif