hp-saturn/saturn_decoder_registers.v
2019-02-19 16:15:46 +01:00

307 lines
No EOL
7.6 KiB
Verilog

`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 <= 0;
o_reg_src1 <= 0;
o_reg_src2 <= 0;
inval_opcode_regs <= 0;
end
if (do_on_first_nibble) begin
// reset values on instruction decode start
case (i_nibble)
4'h4, 4'h5, 4'h6, 4'h7: begin
o_reg_dest <= 0;
o_reg_src1 <= `ALU_REG_IMM;
o_reg_src2 <= 0;
end
default: begin
o_reg_dest <= 0;
o_reg_src1 <= 0;
o_reg_src2 <= 0;
end
endcase
inval_opcode_regs <= 0;
end
/************************************************************************
*
* set registers for specific instructions
*
************************************************************************/
if (do_block_0x) begin
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: o_reg_dest <= `ALU_REG_ST;
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
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};
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]};
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;
end
if (do_block_pointer_arith_const) begin
o_reg_src2 <= `ALU_REG_IMM;
end
if (do_block_2x) begin
o_reg_dest <= `ALU_REG_P;
o_reg_src1 <= `ALU_REG_IMM;
end
if (do_block_3x) begin
o_reg_dest <= `ALU_REG_C;
o_reg_src1 <= `ALU_REG_IMM;
end
if (do_block_8x) begin
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 <= 0;
o_reg_src1 <= `ALU_REG_IMM;
o_reg_src2 <= 0;
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
endcase
end
if (do_block_80Cx) begin
o_reg_dest <= `ALU_REG_C;
o_reg_src1 <= `ALU_REG_P;
o_reg_src2 <= 0;
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 <= 0;
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 <= 0;
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_HST;
o_reg_src2 <= `ALU_REG_IMM;
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
case ({i_nibble[3],i_nibble[2]})
2'b00: begin
o_reg_dest <= reg_ABCD;
o_reg_src1 <= `ALU_REG_ZERO;
o_reg_src2 <= 0;
end
2'b01: begin
o_reg_dest <= reg_ABCD;
o_reg_src1 <= reg_BCAC;
o_reg_src2 <= 0;
end
2'b10: begin
o_reg_dest <= reg_BCAC;
o_reg_src1 <= reg_ABCD;
o_reg_src2 <= 0;
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 <= 0;
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 <= 0;
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 <= 0;
end
endcase
end
if (do_block_Fx) begin
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