2019-02-11 21:29:04 +01:00
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Instruction decoder module
|
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
module saturn_decoder(
|
|
|
|
i_clk,
|
|
|
|
i_reset,
|
|
|
|
i_cycles,
|
2019-02-11 22:57:00 +01:00
|
|
|
i_en_dbg,
|
2019-02-11 21:29:04 +01:00
|
|
|
i_en_dec,
|
2019-02-12 08:21:32 +01:00
|
|
|
i_stalled,
|
2019-02-12 07:48:25 +01:00
|
|
|
i_pc,
|
2019-02-11 22:57:00 +01:00
|
|
|
i_nibble,
|
2019-02-12 07:48:25 +01:00
|
|
|
o_inc_pc,
|
2019-02-11 22:57:00 +01:00
|
|
|
o_dec_error);
|
2019-02-11 21:29:04 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* module input / output ports
|
|
|
|
*/
|
|
|
|
input wire i_clk;
|
|
|
|
input wire i_reset;
|
|
|
|
input wire [31:0] i_cycles;
|
2019-02-11 22:57:00 +01:00
|
|
|
input wire i_en_dbg;
|
2019-02-11 21:29:04 +01:00
|
|
|
input wire i_en_dec;
|
2019-02-12 08:21:32 +01:00
|
|
|
input wire i_stalled;
|
2019-02-12 07:48:25 +01:00
|
|
|
input wire [19:0] i_pc;
|
2019-02-11 21:29:04 +01:00
|
|
|
input wire [3:0] i_nibble;
|
|
|
|
|
2019-02-12 07:48:25 +01:00
|
|
|
output reg o_inc_pc;
|
2019-02-11 22:57:00 +01:00
|
|
|
output reg o_dec_error;
|
|
|
|
|
2019-02-11 21:29:04 +01:00
|
|
|
/*
|
|
|
|
* state registers
|
|
|
|
*/
|
|
|
|
|
2019-02-12 00:07:12 +01:00
|
|
|
reg ins_decoded;
|
2019-02-11 21:29:04 +01:00
|
|
|
reg [31:0] instr_ctr;
|
|
|
|
|
|
|
|
initial begin
|
2019-02-11 21:36:02 +01:00
|
|
|
`ifdef SIM
|
2019-02-11 22:29:13 +01:00
|
|
|
// $monitor({"i_clk %b | i_reset %b | i_cycles %d | i_en_dec %b | i_en_exec %b |",
|
|
|
|
// " continue %b | instr_start %b | i_nibble %h"},
|
|
|
|
// i_clk, i_reset, i_cycles, i_en_dec, i_en_exec, continue,
|
|
|
|
// instr_start, i_nibble);
|
2019-02-12 07:48:25 +01:00
|
|
|
// $monitor("i_en_dec %b | i_cycles %d | nb %h | cont %b | b0x %b | rtn %b | sxm %b | sc %b | cv %b",
|
|
|
|
// i_en_dec, i_cycles, i_nibble, continue, block_0x, ins_rtn, set_xm, set_carry, carry_val);
|
2019-02-11 21:36:02 +01:00
|
|
|
`endif
|
2019-02-11 21:29:04 +01:00
|
|
|
end
|
|
|
|
|
2019-02-11 22:57:00 +01:00
|
|
|
/*
|
|
|
|
* debugger
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
always @(posedge i_clk) begin
|
2019-02-12 08:21:32 +01:00
|
|
|
if (!i_reset && i_en_dbg && !i_stalled)
|
|
|
|
if (!continue && ins_decoded) begin
|
2019-02-11 22:57:00 +01:00
|
|
|
`ifdef SIM
|
2019-02-12 00:07:12 +01:00
|
|
|
$write("%5h ", ins_addr);
|
|
|
|
if (ins_rtn) begin
|
|
|
|
$write("RTN");
|
|
|
|
if (set_xm) $write("SXM");
|
|
|
|
if (set_carry) $write("%sC", carry_val?"S":"C");
|
|
|
|
$display("");
|
|
|
|
end
|
2019-02-12 07:48:25 +01:00
|
|
|
if (ins_set_mode) begin
|
|
|
|
$display("SET%s", mode_dec?"DEC":"HEX");
|
|
|
|
end
|
|
|
|
if (ins_rstk_c) begin
|
|
|
|
$display("%s", direction?"C=RSTK":"RSTK=C");
|
|
|
|
end
|
2019-02-11 22:57:00 +01:00
|
|
|
`endif
|
2019-02-12 00:07:12 +01:00
|
|
|
end
|
2019-02-11 22:57:00 +01:00
|
|
|
end
|
|
|
|
|
2019-02-12 00:07:12 +01:00
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* handle decoding of the fist nibble
|
2019-02-11 21:29:04 +01:00
|
|
|
* that's pretty simple though, will get tougher later on :-)
|
2019-02-12 00:07:12 +01:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
2019-02-11 21:29:04 +01:00
|
|
|
|
2019-02-12 07:48:25 +01:00
|
|
|
// general variables
|
2019-02-12 00:07:12 +01:00
|
|
|
reg [19:0] ins_addr;
|
2019-02-12 07:48:25 +01:00
|
|
|
reg continue;
|
|
|
|
|
2019-02-12 00:07:12 +01:00
|
|
|
reg block_0x;
|
2019-02-11 21:29:04 +01:00
|
|
|
|
2019-02-12 07:48:25 +01:00
|
|
|
// generic
|
|
|
|
reg direction;
|
2019-02-12 00:07:12 +01:00
|
|
|
|
2019-02-12 07:48:25 +01:00
|
|
|
// rtn specific
|
|
|
|
reg ins_rtn;
|
|
|
|
reg set_xm;
|
|
|
|
reg set_carry;
|
|
|
|
reg carry_val;
|
|
|
|
|
|
|
|
// setdec/hex
|
|
|
|
reg ins_set_mode;
|
|
|
|
reg mode_dec;
|
|
|
|
|
|
|
|
// rstk and c
|
|
|
|
reg ins_rstk_c;
|
2019-02-11 21:29:04 +01:00
|
|
|
|
|
|
|
always @(posedge i_clk) begin
|
|
|
|
if (i_reset) begin
|
2019-02-12 07:48:25 +01:00
|
|
|
continue <= 0;
|
|
|
|
o_inc_pc <= 1;
|
|
|
|
o_dec_error <= 0;
|
|
|
|
ins_decoded <= 0;
|
|
|
|
|
2019-02-11 21:29:04 +01:00
|
|
|
end else begin
|
2019-02-12 08:21:32 +01:00
|
|
|
if (i_en_dec && !i_stalled) begin
|
2019-02-12 07:48:25 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* stuff that is always done
|
|
|
|
*/
|
|
|
|
o_inc_pc <= 1; // may be set to 0 later
|
|
|
|
|
|
|
|
/*
|
|
|
|
* cleanup
|
|
|
|
*/
|
2019-02-12 00:07:12 +01:00
|
|
|
if (!continue) begin
|
2019-02-12 07:48:25 +01:00
|
|
|
continue <= 1;
|
|
|
|
ins_decoded <= 0;
|
2019-02-12 00:07:12 +01:00
|
|
|
// store the address where the instruction starts
|
2019-02-12 07:48:25 +01:00
|
|
|
ins_addr <= i_pc;
|
|
|
|
|
|
|
|
// cleanup
|
|
|
|
direction <= 0;
|
|
|
|
|
|
|
|
ins_rtn <= 0;
|
|
|
|
set_xm <= 0;
|
|
|
|
set_carry <= 0;
|
|
|
|
carry_val <= 0;
|
|
|
|
|
|
|
|
ins_set_mode <= 0;
|
|
|
|
mode_dec <= 0;
|
|
|
|
|
|
|
|
ins_rstk_c <= 0;
|
|
|
|
end
|
|
|
|
|
|
|
|
/*
|
|
|
|
* x first nibble
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!continue) begin
|
2019-02-11 22:29:13 +01:00
|
|
|
// assign block regs
|
2019-02-11 22:57:00 +01:00
|
|
|
case (i_nibble)
|
|
|
|
4'h0: block_0x <= 1;
|
|
|
|
default: begin
|
|
|
|
`ifdef SIM
|
2019-02-12 00:07:12 +01:00
|
|
|
$display("new_instruction: nibble %h not handled", i_nibble);
|
2019-02-11 22:57:00 +01:00
|
|
|
`endif
|
|
|
|
o_dec_error <= 1;
|
|
|
|
end
|
|
|
|
endcase
|
2019-02-11 22:29:13 +01:00
|
|
|
end
|
2019-02-12 00:07:12 +01:00
|
|
|
|
2019-02-12 07:48:25 +01:00
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* 0x
|
|
|
|
*
|
|
|
|
* 00 RTNSXM
|
|
|
|
* 01 RTN
|
|
|
|
* 02 RTNSC
|
|
|
|
* 03 RTNCC
|
2019-02-12 08:21:32 +01:00
|
|
|
* 04 SETHEX
|
|
|
|
* 05 SETDEC
|
|
|
|
* 06 RSTK=C
|
|
|
|
* 07 C=RSTK
|
2019-02-12 07:48:25 +01:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
2019-02-11 21:29:04 +01:00
|
|
|
|
2019-02-11 22:29:13 +01:00
|
|
|
if (continue && block_0x) begin
|
|
|
|
case (i_nibble)
|
2019-02-12 07:48:25 +01:00
|
|
|
4'h0, 4'h1, 4'h2, 4'h3: begin
|
|
|
|
ins_rtn <= 1;
|
|
|
|
set_xm <= (i_nibble == 4'h0);
|
|
|
|
set_carry <= (i_nibble[3:1] == 1);
|
|
|
|
carry_val <= (i_nibble[1] && i_nibble[0]);
|
|
|
|
end
|
|
|
|
4'h4, 4'h5 : begin
|
|
|
|
ins_set_mode <= 1;
|
|
|
|
mode_dec <= (i_nibble[0]);
|
|
|
|
end
|
|
|
|
4'h6, 6'h7 : begin
|
|
|
|
ins_rstk_c <= 1;
|
|
|
|
direction <= (i_nibble[0]);
|
|
|
|
end
|
2019-02-11 22:57:00 +01:00
|
|
|
default: begin
|
|
|
|
`ifdef SIM
|
|
|
|
$display("block_0x: nibble %h not handled", i_nibble);
|
|
|
|
`endif
|
|
|
|
o_dec_error <= 1;
|
|
|
|
end
|
2019-02-11 22:29:13 +01:00
|
|
|
endcase
|
2019-02-12 07:48:25 +01:00
|
|
|
continue <= (i_nibble == 4'hE);
|
2019-02-12 00:07:12 +01:00
|
|
|
ins_decoded <= (i_nibble != 4'hE);
|
2019-02-12 07:48:25 +01:00
|
|
|
end
|
2019-02-11 22:29:13 +01:00
|
|
|
|
|
|
|
|
2019-02-12 00:07:12 +01:00
|
|
|
|
|
|
|
|
2019-02-12 07:48:25 +01:00
|
|
|
end
|
|
|
|
end
|
2019-02-11 21:29:04 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
endmodule
|