2021-02-15 23:55:09 +01:00
|
|
|
`include "cpu_pkg.svh"
|
|
|
|
|
|
|
|
import cpu_pkg::*;
|
|
|
|
|
|
|
|
module control (
|
|
|
|
input logic clk_i,
|
|
|
|
input logic nreset_i,
|
2021-02-16 22:13:50 +01:00
|
|
|
|
|
|
|
input logic [ 7:0] rdata_i,
|
|
|
|
|
2021-02-20 16:00:01 +01:00
|
|
|
input logic [ 7:0] f_i,
|
|
|
|
|
2021-02-15 23:55:09 +01:00
|
|
|
output state_t state_o,
|
|
|
|
|
2021-02-16 22:13:50 +01:00
|
|
|
output logic [15:0] pc_o,
|
2021-02-17 00:05:46 +01:00
|
|
|
output logic [15:0] sp_o,
|
2021-02-16 22:13:50 +01:00
|
|
|
|
|
|
|
output logic instr_valid_o,
|
|
|
|
output logic instr_undef_o,
|
|
|
|
output logic [ 7:0] operand8_o,
|
2021-02-17 00:05:46 +01:00
|
|
|
output logic [15:0] operand16_o,
|
|
|
|
|
|
|
|
output logic alu_op_valid_o,
|
|
|
|
output alu_op_t alu_op_o,
|
2021-02-20 23:57:15 +01:00
|
|
|
output logic reg_write_alu_o,
|
2021-02-17 00:05:46 +01:00
|
|
|
output op_src_t op_src_o,
|
2021-02-17 23:40:24 +01:00
|
|
|
output op_dest_t op_dest_o,
|
2021-02-20 16:56:22 +01:00
|
|
|
output reg8_t reg8_dest_o,
|
2021-02-19 22:53:13 +01:00
|
|
|
output reg8_t reg8_src_o,
|
2021-02-19 00:22:26 +01:00
|
|
|
output alu16_op_t alu16_op_o,
|
|
|
|
output reg16_t reg16_src_o,
|
2021-02-17 23:40:24 +01:00
|
|
|
output reg16_t reg16_dest_o,
|
|
|
|
|
2021-02-19 00:22:26 +01:00
|
|
|
output logic memory_we_o,
|
2021-02-17 23:40:24 +01:00
|
|
|
output adr_src_t adr_src_o
|
2021-02-15 23:55:09 +01:00
|
|
|
);
|
|
|
|
|
2021-02-16 22:13:50 +01:00
|
|
|
logic nreset_r;
|
2021-02-20 23:10:47 +01:00
|
|
|
logic halted_r;
|
2021-02-16 22:13:50 +01:00
|
|
|
|
|
|
|
logic state_we;
|
2021-02-15 23:55:09 +01:00
|
|
|
state_t state_r;
|
|
|
|
state_t state_next;
|
|
|
|
|
|
|
|
logic pc_we;
|
|
|
|
logic [15:0] pc_r;
|
|
|
|
logic [15:0] pc_next;
|
|
|
|
|
|
|
|
|
2021-02-17 00:05:46 +01:00
|
|
|
logic sp_we;
|
|
|
|
logic [15:0] sp_r;
|
|
|
|
logic [15:0] sp_next;
|
|
|
|
|
2021-02-16 22:13:50 +01:00
|
|
|
logic instr_pc_we;
|
|
|
|
logic [15:0] instr_pc_r;
|
|
|
|
logic [15:0] instr_pc_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;
|
2021-02-22 23:20:47 +01:00
|
|
|
logic decoder_is_multicycle;
|
2021-02-16 22:13:50 +01:00
|
|
|
logic decoder_is_undef;
|
2021-02-20 16:56:22 +01:00
|
|
|
logic decoder_alu_op_valid;
|
2021-02-19 00:22:26 +01:00
|
|
|
logic decoder_memory_we;
|
2021-02-17 23:40:24 +01:00
|
|
|
adr_src_t decoder_adr_src;
|
2021-02-23 00:07:10 +01:00
|
|
|
logic decoder_sp_we;
|
2021-02-16 22:13:50 +01:00
|
|
|
|
|
|
|
logic is_undef;
|
|
|
|
logic pc_incr;
|
|
|
|
logic instr_valid;
|
2021-02-20 16:00:01 +01:00
|
|
|
logic branch_taken;
|
|
|
|
logic branch_cc_true;
|
2021-02-23 00:07:10 +01:00
|
|
|
logic branch_always;
|
2021-02-16 22:13:50 +01:00
|
|
|
|
2021-02-17 00:05:46 +01:00
|
|
|
sp_src_t sp_src;
|
2021-02-20 16:00:01 +01:00
|
|
|
pc_src_t pc_src;
|
|
|
|
cc_t cc;
|
2021-02-17 00:05:46 +01:00
|
|
|
|
2021-02-16 22:13:50 +01:00
|
|
|
always_ff @(posedge clk_i) begin
|
|
|
|
nreset_r <= nreset_i;
|
2021-02-15 23:55:09 +01:00
|
|
|
end
|
|
|
|
|
2021-02-20 23:10:47 +01:00
|
|
|
always_ff @(posedge clk_i or negedge nreset_i) begin
|
|
|
|
if (~nreset_i)
|
|
|
|
halted_r <= 1'b0;
|
|
|
|
else if (is_undef)
|
|
|
|
halted_r <= halted_r | is_undef;
|
|
|
|
end
|
|
|
|
|
2021-02-16 22:13:50 +01:00
|
|
|
`DEF_FF(state_r, state_next, state_we, ST0_ADDR);
|
|
|
|
`DEF_FF(pc_r, pc_next, pc_we, '0);
|
2021-02-17 00:05:46 +01:00
|
|
|
`DEF_FF(sp_r, sp_next, sp_we, '0);
|
2021-02-16 22:13:50 +01:00
|
|
|
`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);
|
|
|
|
|
2021-02-20 23:10:47 +01:00
|
|
|
assign pc_we = (nreset_r & ~is_undef & ~halted_r) & (pc_incr | branch_taken);
|
2021-02-23 00:07:10 +01:00
|
|
|
assign pc_next = (branch_taken & pc_src == PC_SRC_OPERAND8) ? (pc_r + {{8{operand0_r[7]}}, operand0_r}) :
|
|
|
|
(branch_taken & pc_src == PC_SRC_OPERAND16) ? {operand1_r, operand0_r} :
|
|
|
|
(pc_r + 16'b1);
|
2021-02-15 23:55:09 +01:00
|
|
|
|
2021-02-23 00:07:10 +01:00
|
|
|
assign sp_we = instr_valid & decoder_sp_we;
|
|
|
|
assign sp_next = (sp_src == SP_SRC_OPERAND16) ? {operand1_r, operand0_r} :
|
|
|
|
(sp_src == SP_SRC_INC) ? (sp_r + 16'h01) :
|
|
|
|
(sp_src == SP_SRC_DEC) ? (sp_r + 16'hFFFF) :
|
|
|
|
'0;
|
2021-02-17 00:05:46 +01:00
|
|
|
|
2021-02-16 22:13:50 +01:00
|
|
|
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;
|
|
|
|
|
2021-02-20 23:10:47 +01:00
|
|
|
assign state_we = nreset_r & ~is_undef & ~halted_r;
|
2021-02-15 23:55:09 +01:00
|
|
|
always_comb begin
|
|
|
|
case (state_r)
|
|
|
|
ST0_ADDR: state_next = ST1_DEC;
|
2021-02-22 23:20:47 +01:00
|
|
|
ST1_DEC: state_next = decoder_need_instr1 ? ST2_DEC : ST2_EXEC;
|
|
|
|
ST2_EXEC: state_next = decoder_is_multicycle ? ST3_EXEC : ST0_ADDR;
|
2021-02-16 22:13:50 +01:00
|
|
|
|
2021-02-19 22:53:13 +01:00
|
|
|
ST2_DEC: state_next = decoder_need_instr2 ? ST3_DEC : ST3_EXEC;
|
2021-02-16 22:13:50 +01:00
|
|
|
ST3_DEC: state_next = ST4_EXEC;
|
2021-02-19 22:53:13 +01:00
|
|
|
ST3_EXEC: state_next = ST0_ADDR;
|
2021-02-23 00:07:10 +01:00
|
|
|
ST4_EXEC: state_next = decoder_is_multicycle ? ST5_EXEC : ST0_ADDR;
|
|
|
|
ST5_EXEC: state_next = ST0_ADDR;
|
2021-02-15 23:55:09 +01:00
|
|
|
endcase
|
|
|
|
end
|
|
|
|
|
2021-02-16 22:13:50 +01:00
|
|
|
decode decode_inst (
|
|
|
|
.instr0_i (decoder_instr0_selected),
|
|
|
|
.instr1_i (decoder_instr1_selected),
|
|
|
|
.instr2_i (decoder_instr2_selected),
|
2021-02-17 00:05:46 +01:00
|
|
|
.state_i (state_r),
|
|
|
|
|
2021-02-22 23:20:47 +01:00
|
|
|
.need_instr1_o (decoder_need_instr1),
|
|
|
|
.need_instr2_o (decoder_need_instr2),
|
|
|
|
.is_multicycle_o(decoder_is_multicycle),
|
|
|
|
.undef_o (decoder_is_undef),
|
2021-02-17 00:05:46 +01:00
|
|
|
|
2021-02-23 00:07:10 +01:00
|
|
|
.sp_we_o (decoder_sp_we),
|
2021-02-17 00:05:46 +01:00
|
|
|
.sp_src_o (sp_src),
|
|
|
|
|
2021-02-20 16:56:22 +01:00
|
|
|
.alu_op_valid_o(decoder_alu_op_valid),
|
2021-02-17 00:05:46 +01:00
|
|
|
.alu_op_o (alu_op_o),
|
2021-02-20 23:57:15 +01:00
|
|
|
.reg_write_alu_o(reg_write_alu_o),
|
2021-02-17 00:05:46 +01:00
|
|
|
.op_src_o (op_src_o),
|
2021-02-17 23:40:24 +01:00
|
|
|
.op_dest_o (op_dest_o),
|
2021-02-17 00:05:46 +01:00
|
|
|
|
2021-02-20 16:56:22 +01:00
|
|
|
.reg8_dest_o (reg8_dest_o),
|
2021-02-19 22:53:13 +01:00
|
|
|
.reg8_src_o (reg8_src_o),
|
|
|
|
|
2021-02-19 00:22:26 +01:00
|
|
|
.alu16_op_o (alu16_op_o),
|
|
|
|
.reg16_src_o (reg16_src_o),
|
2021-02-17 23:40:24 +01:00
|
|
|
.reg16_dest_o (reg16_dest_o),
|
2021-02-19 00:22:26 +01:00
|
|
|
|
|
|
|
.memory_we_o (decoder_memory_we),
|
2021-02-20 16:00:01 +01:00
|
|
|
.adr_src_o (decoder_adr_src),
|
2021-02-23 00:07:10 +01:00
|
|
|
.branch_always_o(branch_always),
|
2021-02-20 16:00:01 +01:00
|
|
|
.cc_o (cc),
|
|
|
|
.pc_src_o (pc_src)
|
2021-02-16 22:13:50 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2021-02-19 22:53:13 +01:00
|
|
|
assign is_undef = instr_valid & decoder_is_undef;
|
2021-02-23 00:07:10 +01:00
|
|
|
assign instr_valid = (state_r == ST2_EXEC | state_r == ST3_EXEC | state_r == ST4_EXEC | state_r == ST5_EXEC);
|
2021-02-20 16:56:22 +01:00
|
|
|
assign alu_op_valid_o = decoder_alu_op_valid & instr_valid;
|
2021-02-16 22:13:50 +01:00
|
|
|
|
|
|
|
assign pc_incr = (state_r == ST0_ADDR) | (state_r == ST1_DEC & decoder_need_instr1) | (state_r == ST2_DEC & decoder_need_instr2);
|
|
|
|
|
2021-02-23 00:07:10 +01:00
|
|
|
assign branch_taken = instr_valid & (pc_src != PC_SRC_SEQ) & (branch_cc_true | branch_always);
|
2021-02-20 16:00:01 +01:00
|
|
|
assign branch_cc_true = ((cc == CC_NZ) & ~f_i[7]) |
|
|
|
|
((cc == CC_Z) & f_i[7]) |
|
|
|
|
((cc == CC_NC) & ~f_i[4]) |
|
|
|
|
((cc == CC_C) & f_i[4]);
|
|
|
|
|
2021-02-15 23:55:09 +01:00
|
|
|
assign state_o = state_r;
|
|
|
|
assign pc_o = pc_r;
|
2021-02-17 00:05:46 +01:00
|
|
|
assign sp_o = sp_r;
|
2021-02-15 23:55:09 +01:00
|
|
|
|
2021-02-16 22:13:50 +01:00
|
|
|
assign instr_valid_o = instr_valid;
|
|
|
|
assign instr_undef_o = is_undef;
|
|
|
|
|
|
|
|
assign operand8_o = operand0_r;
|
|
|
|
assign operand16_o = {operand1_r, operand0_r};
|
|
|
|
|
2021-02-19 22:53:13 +01:00
|
|
|
assign memory_we_o = instr_valid & decoder_memory_we;
|
|
|
|
assign adr_src_o = instr_valid ? decoder_adr_src :
|
|
|
|
ADR_SRC_PC;
|
2021-02-17 23:40:24 +01:00
|
|
|
|
2021-02-15 23:55:09 +01:00
|
|
|
endmodule : control
|