hp-saturn/saturn-core.v

362 lines
7.4 KiB
Coq
Raw Normal View History

2019-02-06 10:40:55 +01:00
/*
* Licence: GPLv3 or later
*/
2019-02-04 20:36:47 +01:00
`default_nettype none //
2019-02-11 21:29:04 +01:00
// `include "bus_commands.v"
// `include "hp48_00_bus.v"
// `include "dbg_module.v"
`include "saturn-decoder.v"
`include "saturn-alu.v"
2019-02-04 15:02:33 +01:00
/**************************************************************************************************
*
*
2019-02-05 08:49:14 +01:00
*
*
*
*/
2019-02-06 10:40:55 +01:00
2019-02-04 17:14:08 +01:00
`ifdef SIM
2019-02-04 18:17:14 +01:00
module saturn_core (
2019-02-12 14:49:33 +01:00
input clk,
input reset,
output [0:0] halt,
2019-02-07 22:54:06 +01:00
output [3:0] busstate,
2019-02-12 14:49:33 +01:00
output [11:0] decstate
2019-02-04 18:17:14 +01:00
);
2019-02-04 17:46:29 +01:00
`else
2019-02-04 18:17:14 +01:00
module saturn_core (
2019-02-12 14:49:33 +01:00
input clk_25mhz,
input [6:0] btn,
2019-02-04 22:08:17 +01:00
output [7:0] led
2019-02-04 09:59:35 +01:00
);
2019-02-04 22:08:17 +01:00
wire clk;
wire reset;
2019-02-07 22:54:06 +01:00
reg clk2;
2019-02-04 18:17:14 +01:00
assign clk = clk_25mhz;
assign reset = btn[1];
`endif
2019-02-04 09:59:35 +01:00
2019-02-07 22:54:06 +01:00
// clocks
2019-02-12 08:48:13 +01:00
reg [1:0] clk_phase;
2019-02-11 20:27:51 +01:00
reg en_reset;
2019-02-13 22:43:04 +01:00
reg en_alu_dump; // phase 0
2019-02-11 19:24:57 +01:00
reg en_debugger; // phase 0
reg en_bus_send; // phase 0
reg en_bus_recv; // phase 1
reg en_alu_prep; // phase 1
reg en_alu_calc; // phase 2
reg en_inst_dec; // phase 2
2019-02-13 22:43:04 +01:00
reg en_alu_init; // phase 3
2019-02-11 19:49:22 +01:00
reg en_alu_save; // phase 3
2019-02-11 19:24:57 +01:00
reg en_inst_exec; // phase 3
2019-02-11 19:49:22 +01:00
reg clock_end;
2019-02-12 08:48:13 +01:00
reg [31:0] cycle_ctr;
reg [31:0] max_cycle;
2019-02-07 22:54:06 +01:00
2019-02-04 09:59:35 +01:00
// state machine stuff
2019-02-07 22:54:06 +01:00
wire halt;
2019-02-12 08:48:13 +01:00
2019-02-11 19:49:22 +01:00
// hp48_bus bus_ctrl (
// .strobe (bus_strobe),
// .reset (reset),
// .address (bus_address),
// .command (bus_command),
// .nibble_in (bus_nibble_in),
// .nibble_out (bus_nibble_out),
// .bus_error (bus_error)
// );
saturn_decoder m_decoder (
2019-02-12 12:43:36 +01:00
.i_clk (clk),
.i_reset (reset),
.i_cycles (cycle_ctr),
.i_en_dbg (en_debugger),
.i_en_dec (en_inst_dec),
.i_pc (reg_pc),
.i_stalled (stalled),
.i_nibble (nibble_in),
.i_reg_p (reg_p),
.o_inc_pc (inc_pc),
.o_push (push),
.o_pop (pop),
2019-02-12 12:43:36 +01:00
.o_dec_error (inv_opcode),
.o_alu_debug (alu_debug),
2019-02-12 08:48:13 +01:00
2019-02-12 12:43:36 +01:00
.o_ins_addr (ins_addr),
.o_ins_decoded (ins_decoded),
.o_fields_table (fields_table),
.o_field (field),
.o_field_start (field_start),
.o_field_last (field_last),
2019-02-13 22:43:04 +01:00
.o_imm_value (imm_value),
2019-02-12 12:43:36 +01:00
.o_alu_op (alu_op),
.o_alu_no_stall (alu_no_stall),
2019-02-13 22:43:04 +01:00
.o_reg_dest (reg_dest),
.o_reg_src1 (reg_src1),
.o_reg_src2 (reg_src2),
2019-02-12 12:43:36 +01:00
.o_direction (direction),
.o_ins_rtn (ins_rtn),
.o_set_xm (set_xm),
.o_set_carry (set_carry),
.o_carry_val (carry_val),
.o_ins_set_mode (ins_set_mode),
2019-02-13 22:43:04 +01:00
.o_mode_dec (mode_dec),
.o_ins_alu_op (ins_alu_op)
2019-02-11 21:29:04 +01:00
);
wire [0:0] inc_pc;
wire [0:0] push;
wire [0:0] pop;
wire [0:0] inv_opcode;
wire [0:0] alu_debug;
2019-02-12 12:43:36 +01:00
wire [19:0] ins_addr;
wire ins_decoded;
wire [1:0] fields_table;
wire [3:0] field;
wire [3:0] field_start;
wire [3:0] field_last;
2019-02-13 22:43:04 +01:00
wire [3:0] imm_value;
2019-02-12 12:43:36 +01:00
wire [4:0] alu_op;
wire [0:0] alu_no_stall;
2019-02-13 22:43:04 +01:00
wire [4:0] reg_dest;
wire [4:0] reg_src1;
wire [4:0] reg_src2;
2019-02-12 12:43:36 +01:00
wire direction;
wire ins_rtn;
wire set_xm;
wire set_carry;
wire carry_val;
wire ins_set_mode;
wire mode_dec;
2019-02-13 22:43:04 +01:00
wire ins_alu_op;
2019-02-12 12:43:36 +01:00
saturn_alu m_alu (
2019-02-13 22:43:04 +01:00
.i_clk (clk),
.i_reset (reset),
.i_en_alu_dump (en_alu_dump),
.i_en_alu_prep (en_alu_prep),
.i_en_alu_calc (en_alu_calc),
.i_en_alu_init (en_alu_init),
.i_en_alu_save (en_alu_save),
.i_push (push),
.i_pop (pop),
.i_alu_debug (alu_debug),
2019-02-13 22:43:04 +01:00
.o_alu_stall_dec (alu_stall),
.i_ins_decoded (ins_decoded),
.i_field_start (field_start),
.i_field_last (field_last),
.i_imm_value (imm_value),
.i_alu_op (alu_op),
.i_alu_no_stall (alu_no_stall),
2019-02-13 22:43:04 +01:00
.i_reg_dest (reg_dest),
.i_reg_src1 (reg_src1),
.i_reg_src2 (reg_src2),
.i_ins_alu_op (ins_alu_op),
.o_reg_p (reg_p),
.o_pc (reg_pc)
);
2019-02-12 12:43:36 +01:00
// interconnections
2019-02-13 22:43:04 +01:00
wire [0:0] alu_stall;
2019-02-12 12:43:36 +01:00
wire [3:0] reg_p;
wire [19:0] reg_pc;
2019-02-12 12:43:36 +01:00
/*
* test rom...
*/
2019-02-13 22:43:04 +01:00
`ifdef SIM
reg [3:0] rom [0:2**20];
`else
2019-02-13 23:18:50 +01:00
reg [3:0] rom [0:2**10];
2019-02-13 22:43:04 +01:00
`endif
// `define DEBUG_CLOCKS
2019-02-07 22:54:06 +01:00
initial
begin
2019-02-13 22:43:04 +01:00
`ifdef SIM
2019-02-13 22:43:04 +01:00
$readmemh("rom-gx-r.hex", rom);
// $readmemh( "testrom-2.hex", rom);
2019-02-13 22:43:04 +01:00
`endif
2019-02-12 12:43:36 +01:00
clk_phase = 0;
en_debugger = 0; // phase 0
en_bus_send = 0; // phase 0
en_bus_recv = 0; // phase 1
en_alu_prep = 0; // phase 1
en_alu_calc = 0; // phase 2
en_inst_dec = 0; // phase 2
2019-02-13 22:43:04 +01:00
en_alu_init = 0; // phase 0
2019-02-12 12:43:36 +01:00
en_alu_save = 0; // phase 3
en_inst_exec = 0; // phase 3
clock_end = 0;
cycle_ctr = 0;
2019-02-07 22:54:06 +01:00
2019-02-11 20:27:51 +01:00
`ifdef DEBUG_CLOCKS
$monitor("RST %b | CLK %b | CLKP %d | CYCL %d | PC %5h | eRST %b | eDBG %b | eBSND %b | eBRECV %b | eAPR %b | eACALC %b | eINDC %b | eASAVE %b | eINDX %b",
reset, clk, clk_phase, cycle_ctr, reg_pc, en_reset,
2019-02-11 20:27:51 +01:00
en_debugger, en_bus_send,
2019-02-11 19:49:22 +01:00
en_bus_recv, en_alu_prep,
en_alu_calc, en_inst_dec,
en_alu_save, en_inst_exec);
2019-02-11 20:27:51 +01:00
`endif
2019-02-07 22:54:06 +01:00
end
2019-02-07 22:54:06 +01:00
//--------------------------------------------------------------------------------------------------
//
// clock generation
//
//--------------------------------------------------------------------------------------------------
2019-02-04 17:46:29 +01:00
`define PH_BUS_RECV 1
2019-02-11 19:24:57 +01:00
always @(posedge clk) begin
if (!reset) begin
2019-02-11 20:27:51 +01:00
clk_phase <= clk_phase + 1;
2019-02-13 22:43:04 +01:00
en_alu_dump <= clk_phase[1:0] == 0;
2019-02-11 19:49:22 +01:00
en_debugger <= clk_phase[1:0] == 0;
en_bus_send <= clk_phase[1:0] == 0;
en_bus_recv <= clk_phase[1:0] == `PH_BUS_RECV;
2019-02-11 19:49:22 +01:00
en_alu_prep <= clk_phase[1:0] == 1;
en_alu_calc <= clk_phase[1:0] == 2;
en_inst_dec <= clk_phase[1:0] == 2;
2019-02-13 22:43:04 +01:00
en_alu_init <= clk_phase[1:0] == 3;
2019-02-11 19:49:22 +01:00
en_alu_save <= clk_phase[1:0] == 3;
en_inst_exec <= clk_phase[1:0] == 3;
2019-02-11 20:27:51 +01:00
cycle_ctr <= cycle_ctr + (clk_phase[1:0] == 0);
2019-02-11 19:49:22 +01:00
// stop after 50 clocks
2019-02-11 20:27:51 +01:00
if (cycle_ctr == (max_cycle + 1))
2019-02-11 19:49:22 +01:00
clock_end <= 1;
end else begin
2019-02-11 20:27:51 +01:00
clk_phase <= ~0;
2019-02-13 22:43:04 +01:00
en_alu_dump <= 0;
2019-02-11 19:49:22 +01:00
en_debugger <= 0;
en_bus_send <= 0;
en_bus_recv <= 0;
en_alu_prep <= 0;
en_alu_calc <= 0;
en_inst_dec <= 0;
2019-02-13 22:43:04 +01:00
en_alu_init <= 0;
2019-02-11 19:49:22 +01:00
en_alu_save <= 0;
en_inst_exec <= 0;
2019-02-13 22:43:04 +01:00
clock_end <= 0;
cycle_ctr <= ~0;
max_cycle <= 40;
`ifndef SIM
2019-02-13 22:43:04 +01:00
led[7:0] <= reg_pc[7:0];
`endif
2019-02-11 19:24:57 +01:00
end
end
2019-02-04 09:59:35 +01:00
//--------------------------------------------------------------------------------------------------
//
// test cases
//
//--------------------------------------------------------------------------------------------------
reg [3:0] nibble_in;
2019-02-13 22:43:04 +01:00
wire stalled;
assign stalled = alu_stall;
2019-02-07 22:54:06 +01:00
2019-02-11 21:29:04 +01:00
always @(posedge clk)
2019-02-12 14:49:33 +01:00
if (reset) begin
//reg_pc <= ~0;
2019-02-13 22:43:04 +01:00
// stalled <= 0;
2019-02-12 14:49:33 +01:00
end else begin
if (en_bus_send) begin
// PC handled by ALU
//
// if (inc_pc & !stalled)
// reg_pc <= reg_pc + 1;
// `ifdef SIM
// else
// $write("PC_INC 0: not incrementing PC\n");
// `endif
end
if (en_bus_recv) begin
2019-02-12 14:49:33 +01:00
if (!stalled) begin
$display("BUS_RECV %1d: [%d] %5h => %1h", `PH_BUS_RECV, cycle_ctr, reg_pc, rom[reg_pc]);
2019-02-12 14:49:33 +01:00
nibble_in <= rom[reg_pc];
end
end
2019-02-13 22:43:04 +01:00
// if (en_inst_exec) begin
// if (cycle_ctr == 5) stalled <= 1;
// if (cycle_ctr == 10) stalled <= 0;
// end
end
2019-02-07 22:54:06 +01:00
2019-02-12 12:43:36 +01:00
assign halt = clock_end || inv_opcode;
2019-02-07 22:54:06 +01:00
2019-02-04 22:08:17 +01:00
// Verilator lint_off UNUSED
//wire [N-1:0] unused;
//assign unused = { };
// Verilator lint_on UNUSED
2019-02-04 09:59:35 +01:00
endmodule
`ifdef SIM
2019-02-04 17:46:29 +01:00
module saturn_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-07 22:54:06 +01:00
wire [3:0] busstate;
2019-02-09 19:18:58 +01:00
wire [11: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),
2019-02-07 22:54:06 +01:00
.busstate (busstate),
2019-02-04 15:02:33 +01:00
.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);
2019-02-07 22:54:06 +01:00
@(posedge clk);
@(posedge clk);
2019-02-04 09:59:35 +01:00
reset <= 0;
@(posedge halt);
$finish;
end
endmodule
2019-02-13 22:43:04 +01:00
`endif