Initial work on decoder
Decode the LD SP, $nnnn instruction as our first three-byte instruction.
This commit is contained in:
parent
3191a19f7e
commit
aa92344d10
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
build/.Xil
|
build/.Xil
|
||||||
build/xsim.dir
|
build/xsim.dir
|
||||||
|
build/*.wcfg
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
TB = tb_top
|
TB = tb_top
|
||||||
SOURCES = gb.sv cpu.sv registers.sv control.sv rom.sv tb_top.sv clkgen.sv
|
SOURCES = gb.sv cpu.sv registers.sv control.sv decode.sv rom.sv tb_top.sv clkgen.sv
|
||||||
PATH_SRC = ../rtl:../rtl/cpu:../rtl/shared:../sim/tbench:../sim/shared
|
PATH_SRC = ../rtl:../rtl/cpu:../rtl/shared:../sim/tbench:../sim/shared
|
||||||
|
|
||||||
gb.sdb: cpu.sdb rom.sdb
|
gb.sdb: cpu.sdb rom.sdb
|
||||||
|
@ -5,11 +5,22 @@ import cpu_pkg::*;
|
|||||||
module control (
|
module control (
|
||||||
input logic clk_i,
|
input logic clk_i,
|
||||||
input logic nreset_i,
|
input logic nreset_i,
|
||||||
|
|
||||||
|
input logic [ 7:0] rdata_i,
|
||||||
|
|
||||||
output state_t state_o,
|
output state_t state_o,
|
||||||
|
|
||||||
output logic [15:0] pc_o
|
output logic [15:0] pc_o,
|
||||||
|
|
||||||
|
output logic instr_valid_o,
|
||||||
|
output logic instr_undef_o,
|
||||||
|
output logic [ 7:0] operand8_o,
|
||||||
|
output logic [15:0] operand16_o
|
||||||
);
|
);
|
||||||
|
|
||||||
|
logic nreset_r;
|
||||||
|
|
||||||
|
logic state_we;
|
||||||
state_t state_r;
|
state_t state_r;
|
||||||
state_t state_next;
|
state_t state_next;
|
||||||
|
|
||||||
@ -17,33 +28,107 @@ module control (
|
|||||||
logic [15:0] pc_r;
|
logic [15:0] pc_r;
|
||||||
logic [15:0] pc_next;
|
logic [15:0] pc_next;
|
||||||
|
|
||||||
always_ff @(posedge clk_i or negedge nreset_i) begin
|
|
||||||
if (~nreset_i)
|
logic instr_pc_we;
|
||||||
state_r <= ST0_ADDR;
|
logic [15:0] instr_pc_r;
|
||||||
else
|
logic [15:0] instr_pc_next;
|
||||||
state_r <= state_next;
|
|
||||||
|
logic instr_we;
|
||||||
|
logic [ 7:0] instr_r;
|
||||||
|
logic [ 7:0] instr_next;
|
||||||
|
|
||||||
|
logic operand0_we;
|
||||||
|
logic [ 7:0] operand0_r;
|
||||||
|
logic [ 7:0] operand0_next;
|
||||||
|
|
||||||
|
logic operand1_we;
|
||||||
|
logic [ 7:0] operand1_r;
|
||||||
|
logic [ 7:0] operand1_next;
|
||||||
|
|
||||||
|
logic [ 7:0] decoder_instr0_selected;
|
||||||
|
logic [ 7:0] decoder_instr1_selected;
|
||||||
|
logic [ 7:0] decoder_instr2_selected;
|
||||||
|
logic decoder_need_instr1;
|
||||||
|
logic decoder_need_instr2;
|
||||||
|
logic decoder_is_undef;
|
||||||
|
|
||||||
|
logic is_undef;
|
||||||
|
logic pc_incr;
|
||||||
|
logic instr_valid;
|
||||||
|
|
||||||
|
`define DEF_FF(register, next, we, rst_value) \
|
||||||
|
always_ff @(posedge clk_i or negedge nreset_i) begin \
|
||||||
|
if (~nreset_i) begin \
|
||||||
|
register <= (rst_value); \
|
||||||
|
end else if ((we)) begin \
|
||||||
|
register <= (next); \
|
||||||
|
end \
|
||||||
end
|
end
|
||||||
|
|
||||||
always_ff @(posedge clk_i or negedge nreset_i) begin
|
always_ff @(posedge clk_i) begin
|
||||||
if (~nreset_i)
|
nreset_r <= nreset_i;
|
||||||
pc_r <= '0;
|
|
||||||
else if (pc_we)
|
|
||||||
pc_r <= pc_next;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
assign pc_we = (state_r == ST0_ADDR);
|
`DEF_FF(state_r, state_next, state_we, ST0_ADDR);
|
||||||
|
`DEF_FF(pc_r, pc_next, pc_we, '0);
|
||||||
|
`DEF_FF(instr_pc_r, instr_pc_next, instr_pc_we, '0);
|
||||||
|
`DEF_FF(instr_r, instr_next, instr_we, '0);
|
||||||
|
`DEF_FF(operand0_r, operand0_next, operand0_we, '0);
|
||||||
|
`DEF_FF(operand1_r, operand1_next, operand1_we, '0);
|
||||||
|
|
||||||
|
assign pc_we = nreset_r & pc_incr & ~is_undef;
|
||||||
assign pc_next = (pc_r + 16'b1);
|
assign pc_next = (pc_r + 16'b1);
|
||||||
|
|
||||||
|
assign instr_we = (state_r == ST1_DEC);
|
||||||
|
assign instr_next = rdata_i;
|
||||||
|
|
||||||
|
assign instr_pc_we = (state_r == ST0_ADDR);
|
||||||
|
assign instr_pc_next = pc_r;
|
||||||
|
|
||||||
|
assign operand0_we = (state_r == ST2_DEC);
|
||||||
|
assign operand0_next = rdata_i;
|
||||||
|
|
||||||
|
assign operand1_we = (state_r == ST3_DEC);
|
||||||
|
assign operand1_next = rdata_i;
|
||||||
|
|
||||||
|
assign state_we = nreset_r & ~is_undef;
|
||||||
always_comb begin
|
always_comb begin
|
||||||
case (state_r)
|
case (state_r)
|
||||||
ST0_ADDR: state_next = ST1_DEC;
|
ST0_ADDR: state_next = ST1_DEC;
|
||||||
ST1_DEC: state_next = ST2_EXEC;
|
ST1_DEC: state_next = decoder_need_instr1 ? ST2_DEC : ST2_EXEC;
|
||||||
ST2_EXEC: state_next = ST3_INC_ADDR;
|
ST2_EXEC: state_next = ST0_ADDR;
|
||||||
ST3_INC_ADDR: state_next = ST0_ADDR;
|
|
||||||
|
ST2_DEC: state_next = decoder_need_instr2 ? ST3_DEC : ST0_ADDR;
|
||||||
|
ST3_DEC: state_next = ST4_EXEC;
|
||||||
|
ST4_EXEC: state_next = ST0_ADDR;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
decode decode_inst (
|
||||||
|
.instr0_i (decoder_instr0_selected),
|
||||||
|
.instr1_i (decoder_instr1_selected),
|
||||||
|
.instr2_i (decoder_instr2_selected),
|
||||||
|
.need_instr1_o(decoder_need_instr1),
|
||||||
|
.need_instr2_o(decoder_need_instr2),
|
||||||
|
.undef_o (decoder_is_undef)
|
||||||
|
);
|
||||||
|
|
||||||
|
assign decoder_instr0_selected = (state_r == ST1_DEC) ? rdata_i : instr_r;
|
||||||
|
assign decoder_instr1_selected = (state_r == ST2_DEC) ? rdata_i : operand0_r;
|
||||||
|
assign decoder_instr2_selected = (state_r == ST3_DEC) ? rdata_i : operand1_r;
|
||||||
|
|
||||||
|
assign is_undef = (state_r != ST0_ADDR & decoder_is_undef);
|
||||||
|
assign instr_valid = (state_r == ST4_EXEC);
|
||||||
|
|
||||||
|
assign pc_incr = (state_r == ST0_ADDR) | (state_r == ST1_DEC & decoder_need_instr1) | (state_r == ST2_DEC & decoder_need_instr2);
|
||||||
|
|
||||||
assign state_o = state_r;
|
assign state_o = state_r;
|
||||||
assign pc_o = pc_r;
|
assign pc_o = pc_r;
|
||||||
|
|
||||||
|
assign instr_valid_o = instr_valid;
|
||||||
|
assign instr_undef_o = is_undef;
|
||||||
|
|
||||||
|
assign operand8_o = operand0_r;
|
||||||
|
assign operand16_o = {operand1_r, operand0_r};
|
||||||
|
|
||||||
endmodule : control
|
endmodule : control
|
||||||
|
@ -17,6 +17,7 @@ module cpu (
|
|||||||
control control_inst (
|
control control_inst (
|
||||||
.clk_i (clk_i),
|
.clk_i (clk_i),
|
||||||
.nreset_i(nreset_i),
|
.nreset_i(nreset_i),
|
||||||
|
.rdata_i (rdata_i),
|
||||||
.state_o (state),
|
.state_o (state),
|
||||||
.pc_o (pc)
|
.pc_o (pc)
|
||||||
);
|
);
|
||||||
|
@ -4,7 +4,10 @@ package cpu_pkg;
|
|||||||
ST0_ADDR,
|
ST0_ADDR,
|
||||||
ST1_DEC,
|
ST1_DEC,
|
||||||
ST2_EXEC,
|
ST2_EXEC,
|
||||||
ST3_INC_ADDR
|
ST2_DEC,
|
||||||
|
ST3_INC_ADDR,
|
||||||
|
ST3_DEC,
|
||||||
|
ST4_EXEC
|
||||||
} state_t;
|
} state_t;
|
||||||
|
|
||||||
endpackage
|
endpackage
|
||||||
|
21
rtl/cpu/decode.sv
Normal file
21
rtl/cpu/decode.sv
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
module decode (
|
||||||
|
input [7:0] instr0_i,
|
||||||
|
input [7:0] instr1_i,
|
||||||
|
input [7:0] instr2_i,
|
||||||
|
|
||||||
|
output logic need_instr1_o,
|
||||||
|
output logic need_instr2_o,
|
||||||
|
output logic undef_o
|
||||||
|
);
|
||||||
|
|
||||||
|
logic is_ld_sp_nnnn;
|
||||||
|
|
||||||
|
|
||||||
|
assign is_ld_sp_nnnn = (instr0_i == 7'h31);
|
||||||
|
|
||||||
|
assign need_instr1_o = is_ld_sp_nnnn;
|
||||||
|
assign need_instr2_o = is_ld_sp_nnnn;
|
||||||
|
|
||||||
|
assign undef_o = ~is_ld_sp_nnnn;
|
||||||
|
|
||||||
|
endmodule : decode
|
@ -7,7 +7,7 @@ module clkgen #(
|
|||||||
);
|
);
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
clk_o <= 1'b0;
|
clk_o <= 1'b1;
|
||||||
nreset_o <= 1'b0;
|
nreset_o <= 1'b0;
|
||||||
#RESET_DELAY_NS nreset_o <= 1'b1;
|
#RESET_DELAY_NS nreset_o <= 1'b1;
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user