mirror of
https://github.com/sxpert/hp-saturn
synced 2024-11-16 19:50:19 +01:00
340 lines
No EOL
9 KiB
Verilog
340 lines
No EOL
9 KiB
Verilog
/*
|
|
This file is part of hp_saturn.
|
|
|
|
hp_saturn is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
any later version.
|
|
|
|
hp_saturn is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Foobar. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
`ifndef _SATURN_DECODER_REGISTERS
|
|
`define _SATURN_DECODER_REGISTERS
|
|
|
|
`include "def-alu.v"
|
|
|
|
/******************************************************************************
|
|
*
|
|
* set registers from instruction nibble
|
|
*
|
|
*****************************************************************************/
|
|
|
|
wire [4:0] reg_ABCD;
|
|
wire [4:0] reg_BCAC;
|
|
wire [4:0] reg_ABAC;
|
|
wire [4:0] reg_BCCD;
|
|
wire [4:0] reg_D0D1;
|
|
wire [4:0] reg_DAT0DAT1;
|
|
wire [4:0] reg_A_C;
|
|
|
|
assign reg_ABCD = { 3'b000, i_nibble[1:0]};
|
|
assign reg_BCAC = { 3'b000, i_nibble[0], !(i_nibble[1] || i_nibble[0])};
|
|
assign reg_ABAC = { 3'b000, i_nibble[1] && i_nibble[0], (!i_nibble[1]) && i_nibble[0]};
|
|
assign reg_BCCD = { 3'b000, i_nibble[1] || i_nibble[0], !( i_nibble[1] ^ i_nibble[0])};
|
|
// assign reg_D0D1 = { 4'b0010, (i_nibble[0] && i_nibble[1]) || (i_nibble[2] && i_nibble[3])};
|
|
assign reg_D0D1 = { 4'b0010, i_nibble[0]};
|
|
assign reg_DAT0DAT1 = { 4'b1000, i_nibble[0]};
|
|
assign reg_A_C = { 3'b000, i_nibble[2], 1'b0};
|
|
|
|
always @(posedge i_clk) begin
|
|
|
|
if (i_reset) begin
|
|
o_reg_dest <= `ALU_REG_NOPE;
|
|
o_reg_src1 <= `ALU_REG_NOPE;
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
inval_opcode_regs <= 0;
|
|
end
|
|
|
|
if (do_on_first_nibble) begin
|
|
// reset values on instruction decode start
|
|
case (i_nibble)
|
|
4'h3: begin
|
|
o_reg_dest <= `ALU_REG_C;
|
|
o_reg_src1 <= `ALU_REG_IMM;
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
4'h4, 4'h5, 4'h6, 4'h7: begin
|
|
o_reg_dest <= `ALU_REG_NOPE;
|
|
o_reg_src1 <= `ALU_REG_IMM;
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
default: begin
|
|
o_reg_dest <= `ALU_REG_NOPE;
|
|
o_reg_src1 <= `ALU_REG_NOPE;
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
endcase
|
|
inval_opcode_regs <= 0;
|
|
end
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* set registers for specific instructions
|
|
*
|
|
************************************************************************/
|
|
|
|
if (do_block_0x) begin
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
case (i_nibble)
|
|
4'h6: begin
|
|
o_reg_dest <= `ALU_REG_RSTK;
|
|
o_reg_src1 <= `ALU_REG_C;
|
|
end
|
|
4'h7: begin
|
|
o_reg_dest <= `ALU_REG_C;
|
|
o_reg_src1 <= `ALU_REG_RSTK;
|
|
end
|
|
4'h8: begin
|
|
o_reg_dest <= `ALU_REG_ST;
|
|
o_reg_src1 <= `ALU_REG_NOPE;
|
|
end
|
|
4'h9, 4'hB: begin
|
|
o_reg_dest <= `ALU_REG_C;
|
|
o_reg_src1 <= `ALU_REG_ST;
|
|
end
|
|
4'hA: begin
|
|
o_reg_dest <= `ALU_REG_ST;
|
|
o_reg_src1 <= `ALU_REG_C;
|
|
end
|
|
4'hC, 4'hD: begin
|
|
o_reg_dest <= `ALU_REG_P;
|
|
o_reg_src1 <= `ALU_REG_P;
|
|
end
|
|
default: begin
|
|
// inval_opcode_regs <= 1;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
if (do_block_0Efx && !in_fields_table) begin
|
|
o_reg_dest <= i_nibble[2]?reg_BCAC:reg_ABCD;
|
|
o_reg_src1 <= i_nibble[2]?reg_BCAC:reg_ABCD;
|
|
o_reg_src2 <= i_nibble[2]?reg_ABCD:reg_BCAC;
|
|
end
|
|
|
|
if (do_block_1x) begin
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
case (i_nibble)
|
|
4'h6, 4'h8: begin
|
|
o_reg_dest <= `ALU_REG_D0;
|
|
o_reg_src1 <= `ALU_REG_D0;
|
|
end
|
|
4'h7, 4'hC: begin
|
|
o_reg_dest <= `ALU_REG_D1;
|
|
o_reg_src1 <= `ALU_REG_D1;
|
|
end
|
|
4'h9, 4'hA, 4'hB: begin
|
|
o_reg_dest <= `ALU_REG_D0;
|
|
o_reg_src1 <= `ALU_REG_IMM;
|
|
end
|
|
4'hD, 4'hE, 4'hF: begin
|
|
o_reg_dest <= `ALU_REG_D1;
|
|
o_reg_src1 <= `ALU_REG_IMM;
|
|
end
|
|
default: begin end
|
|
endcase
|
|
end
|
|
|
|
if (do_block_save_to_R_W) begin
|
|
o_reg_dest <= {2'b01, i_nibble[2:0]};
|
|
o_reg_src1 <= {3'b000, i_nibble[3]?2'b10:2'b00};
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
|
|
if (do_block_rest_from_R_W || do_block_exch_with_R_W) begin
|
|
o_reg_dest <= {3'b000, i_nibble[3]?2'b10:2'b00};
|
|
o_reg_src1 <= {2'b01, i_nibble[2:0]};
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
|
|
if (do_block_13x) begin
|
|
o_reg_dest <= i_nibble[1]?reg_A_C:reg_D0D1;
|
|
o_reg_src1 <= i_nibble[2]?`ALU_REG_C:`ALU_REG_A;
|
|
o_reg_src2 <= i_nibble[1]?reg_D0D1:0;
|
|
end
|
|
|
|
if (do_block_14x_15xx) begin
|
|
o_reg_dest <= i_nibble[1]?reg_A_C:reg_DAT0DAT1;
|
|
o_reg_src1 <= i_nibble[1]?reg_DAT0DAT1:reg_A_C;
|
|
o_reg_src2 <= i_nibble[0]?`ALU_REG_D1:`ALU_REG_D0;
|
|
end
|
|
|
|
if (do_block_pointer_arith_const) begin
|
|
o_reg_dest <= `ALU_REG_NOPE;
|
|
o_reg_dest <= `ALU_REG_NOPE;
|
|
o_reg_src2 <= `ALU_REG_IMM;
|
|
end
|
|
|
|
if (do_block_2x) begin
|
|
o_reg_dest <= `ALU_REG_P;
|
|
o_reg_src1 <= `ALU_REG_IMM;
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
|
|
if (do_block_8x) begin
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
case (i_nibble)
|
|
4'h4, 4'h5, 4'h6, 4'h7: begin
|
|
o_reg_dest <= `ALU_REG_ST;
|
|
o_reg_src1 <= `ALU_REG_IMM;
|
|
end
|
|
4'hC, 4'hD, 4'hE, 4'hF: begin
|
|
o_reg_dest <= `ALU_REG_NOPE;
|
|
o_reg_src1 <= `ALU_REG_IMM;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
if (do_block_80x) begin
|
|
case (i_nibble)
|
|
4'h5: begin
|
|
o_reg_dest <= `ALU_REG_ADDR;
|
|
o_reg_src1 <= `ALU_REG_C;
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
4'hC: begin
|
|
o_reg_dest <= `ALU_REG_C;
|
|
o_reg_src1 <= `ALU_REG_P;
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
if (do_block_81Af0x) begin
|
|
o_reg_dest <= { 2'b01, i_nibble[2:0]};
|
|
o_reg_src1 <= i_nibble[3]?`ALU_REG_C:`ALU_REG_A;
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
|
|
if (do_block_81Af1x) begin
|
|
o_reg_dest <= i_nibble[3]?`ALU_REG_C:`ALU_REG_A;
|
|
o_reg_src1 <= { 2'b01, i_nibble[2:0]};
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
|
|
if (do_block_81Af2x) begin
|
|
o_reg_dest <= i_nibble[3]?`ALU_REG_C:`ALU_REG_A;
|
|
o_reg_src1 <= i_nibble[3]?`ALU_REG_C:`ALU_REG_A;
|
|
o_reg_src2 <= { 2'b01, i_nibble[2:0]};
|
|
end
|
|
|
|
if (do_block_82x) begin
|
|
o_reg_dest <= `ALU_REG_HST;
|
|
o_reg_src1 <= `ALU_REG_IMM;
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
|
|
if (do_block_84x_85x) begin
|
|
o_reg_dest <= `ALU_REG_ST;
|
|
o_reg_src1 <= `ALU_REG_IMM;
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
|
|
if (do_block_8Ax) begin
|
|
o_reg_dest <= 0;
|
|
o_reg_src1 <= i_nibble[3]?reg_ABCD:reg_BCAC;
|
|
o_reg_src2 <= i_nibble[3]?`ALU_REG_ZERO:reg_ABCD;
|
|
end
|
|
|
|
if (do_block_Abx || do_block_Dx) begin
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
case ({i_nibble[3],i_nibble[2]})
|
|
2'b00: begin
|
|
o_reg_dest <= reg_ABCD;
|
|
o_reg_src1 <= `ALU_REG_ZERO;
|
|
end
|
|
2'b01: begin
|
|
o_reg_dest <= reg_ABCD;
|
|
o_reg_src1 <= reg_BCAC;
|
|
end
|
|
2'b10: begin
|
|
o_reg_dest <= reg_BCAC;
|
|
o_reg_src1 <= reg_ABCD;
|
|
end
|
|
2'b11: begin // exch
|
|
o_reg_dest <= reg_ABAC;
|
|
o_reg_src1 <= reg_ABAC;
|
|
o_reg_src2 <= reg_BCCD;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
if (do_block_Bax) begin
|
|
case ({i_nibble[3],i_nibble[2]})
|
|
2'b00: begin
|
|
o_reg_dest <= reg_ABCD;
|
|
o_reg_src1 <= reg_ABCD;
|
|
o_reg_src2 <= reg_BCAC;
|
|
end
|
|
2'b01: begin
|
|
o_reg_dest <= reg_ABCD;
|
|
o_reg_src1 <= reg_ABCD;
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
2'b10: begin
|
|
o_reg_dest <= reg_BCAC;
|
|
o_reg_src1 <= reg_BCAC;
|
|
o_reg_src2 <= reg_ABCD;
|
|
end
|
|
2'b11: begin
|
|
o_reg_dest <= reg_ABCD;
|
|
o_reg_src1 <= reg_BCAC;
|
|
o_reg_src2 <= reg_ABCD;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
if (do_block_Bbx) begin
|
|
o_reg_dest <= reg_ABCD;
|
|
o_reg_src1 <= reg_ABCD;
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
|
|
if (do_block_Cx) begin
|
|
case ({i_nibble[3],i_nibble[2]})
|
|
2'b00: begin
|
|
o_reg_dest <= reg_ABCD;
|
|
o_reg_src1 <= reg_ABCD;
|
|
o_reg_src2 <= reg_BCAC;
|
|
end
|
|
2'b01: begin
|
|
o_reg_dest <= reg_ABCD;
|
|
o_reg_src1 <= reg_ABCD;
|
|
o_reg_src2 <= reg_ABCD;
|
|
end
|
|
2'b10: begin
|
|
o_reg_dest <= reg_BCAC;
|
|
o_reg_src1 <= reg_BCAC;
|
|
o_reg_src2 <= reg_ABCD;
|
|
end
|
|
2'b11: begin // reg = reg - 1
|
|
o_reg_dest <= reg_ABCD;
|
|
o_reg_src1 <= reg_ABCD;
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
if (do_block_Fx) begin
|
|
o_reg_src2 <= `ALU_REG_NOPE;
|
|
case (i_nibble)
|
|
4'h8, 4'h9, 4'hA, 4'hB: begin
|
|
o_reg_dest <= reg_ABCD;
|
|
o_reg_src1 <= reg_ABCD;
|
|
end
|
|
endcase
|
|
o_reg_src2 <= 0;
|
|
end
|
|
|
|
end
|
|
|
|
`endif |