Line 29... |
Line 29... |
//
|
//
|
// *Author(s):
|
// *Author(s):
|
// - Olivier Girard, olgirard@gmail.com
|
// - Olivier Girard, olgirard@gmail.com
|
//
|
//
|
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
// $Rev: 106 $
|
// $Rev: 111 $
|
// $LastChangedBy: olivier.girard $
|
// $LastChangedBy: olivier.girard $
|
// $LastChangedDate: 2011-03-25 23:01:03 +0100 (Fri, 25 Mar 2011) $
|
// $LastChangedDate: 2011-05-20 22:39:02 +0200 (Fri, 20 May 2011) $
|
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
`ifdef OMSP_NO_INCLUDE
|
`ifdef OMSP_NO_INCLUDE
|
`else
|
`else
|
`include "openMSP430_defines.v"
|
`include "openMSP430_defines.v"
|
`endif
|
`endif
|
Line 78... |
Line 78... |
mclk, // Main system clock
|
mclk, // Main system clock
|
mdb_in, // Frontend Memory data bus input
|
mdb_in, // Frontend Memory data bus input
|
nmi_evt, // Non-maskable interrupt event
|
nmi_evt, // Non-maskable interrupt event
|
pc_sw, // Program counter software value
|
pc_sw, // Program counter software value
|
pc_sw_wr, // Program counter software write
|
pc_sw_wr, // Program counter software write
|
puc, // Main system reset
|
puc_rst, // Main system reset
|
wdt_irq // Watchdog-timer interrupt
|
wdt_irq // Watchdog-timer interrupt
|
);
|
);
|
|
|
// OUTPUTs
|
// OUTPUTs
|
//=========
|
//=========
|
Line 122... |
Line 122... |
input mclk; // Main system clock
|
input mclk; // Main system clock
|
input [15:0] mdb_in; // Frontend Memory data bus input
|
input [15:0] mdb_in; // Frontend Memory data bus input
|
input nmi_evt; // Non-maskable interrupt event
|
input nmi_evt; // Non-maskable interrupt event
|
input [15:0] pc_sw; // Program counter software value
|
input [15:0] pc_sw; // Program counter software value
|
input pc_sw_wr; // Program counter software write
|
input pc_sw_wr; // Program counter software write
|
input puc; // Main system reset
|
input puc_rst; // Main system reset
|
input wdt_irq; // Watchdog-timer interrupt
|
input wdt_irq; // Watchdog-timer interrupt
|
|
|
|
|
//=============================================================================
|
//=============================================================================
|
// 0) UTILITY FUNCTIONS
|
// 1) UTILITY FUNCTIONS
|
//=============================================================================
|
//=============================================================================
|
|
|
// 16 bits one-hot decoder
|
// 16 bits one-hot decoder
|
function [15:0] one_hot16;
|
function [15:0] one_hot16;
|
input [3:0] binary;
|
input [3:0] binary;
|
Line 150... |
Line 150... |
end
|
end
|
endfunction
|
endfunction
|
|
|
|
|
//=============================================================================
|
//=============================================================================
|
// 1) FRONTEND STATE MACHINE
|
// 2) Parameter definitions
|
|
//=============================================================================
|
|
|
|
//
|
|
// 2.1) Instruction State machine definitons
|
|
//-------------------------------------------
|
|
|
|
parameter I_IRQ_FETCH = `I_IRQ_FETCH;
|
|
parameter I_IRQ_DONE = `I_IRQ_DONE;
|
|
parameter I_DEC = `I_DEC; // New instruction ready for decode
|
|
parameter I_EXT1 = `I_EXT1; // 1st Extension word
|
|
parameter I_EXT2 = `I_EXT2; // 2nd Extension word
|
|
parameter I_IDLE = `I_IDLE; // CPU is in IDLE mode
|
|
|
|
//
|
|
// 2.2) Execution State machine definitons
|
|
//-------------------------------------------
|
|
|
|
parameter E_IRQ_0 = `E_IRQ_0;
|
|
parameter E_IRQ_1 = `E_IRQ_1;
|
|
parameter E_IRQ_2 = `E_IRQ_2;
|
|
parameter E_IRQ_3 = `E_IRQ_3;
|
|
parameter E_IRQ_4 = `E_IRQ_4;
|
|
parameter E_SRC_AD = `E_SRC_AD;
|
|
parameter E_SRC_RD = `E_SRC_RD;
|
|
parameter E_SRC_WR = `E_SRC_WR;
|
|
parameter E_DST_AD = `E_DST_AD;
|
|
parameter E_DST_RD = `E_DST_RD;
|
|
parameter E_DST_WR = `E_DST_WR;
|
|
parameter E_EXEC = `E_EXEC;
|
|
parameter E_JUMP = `E_JUMP;
|
|
parameter E_IDLE = `E_IDLE;
|
|
|
|
|
|
//=============================================================================
|
|
// 3) FRONTEND STATE MACHINE
|
//=============================================================================
|
//=============================================================================
|
|
|
// The wire "conv" is used as state bits to calculate the next response
|
// The wire "conv" is used as state bits to calculate the next response
|
reg [2:0] i_state;
|
reg [2:0] i_state;
|
reg [2:0] i_state_nxt;
|
reg [2:0] i_state_nxt;
|
Line 165... |
Line 200... |
wire [2:0] inst_type_nxt;
|
wire [2:0] inst_type_nxt;
|
wire is_const;
|
wire is_const;
|
reg [15:0] sconst_nxt;
|
reg [15:0] sconst_nxt;
|
reg [3:0] e_state_nxt;
|
reg [3:0] e_state_nxt;
|
|
|
// State machine definitons
|
|
parameter I_IRQ_FETCH = 3'h0;
|
|
parameter I_IRQ_DONE = 3'h1;
|
|
parameter I_DEC = 3'h2; // New instruction ready for decode
|
|
parameter I_EXT1 = 3'h3; // 1st Extension word
|
|
parameter I_EXT2 = 3'h4; // 2nd Extension word
|
|
parameter I_IDLE = 3'h5; // CPU is in IDLE mode
|
|
|
|
// CPU on/off through the debug interface or cpu_en port
|
// CPU on/off through the debug interface or cpu_en port
|
wire cpu_halt_cmd = dbg_halt_cmd | ~cpu_en_s;
|
wire cpu_halt_cmd = dbg_halt_cmd | ~cpu_en_s;
|
|
|
// States Transitions
|
// States Transitions
|
always @(i_state or inst_sz or inst_sz_nxt or pc_sw_wr or exec_done or
|
always @(i_state or inst_sz or inst_sz_nxt or pc_sw_wr or exec_done or
|
exec_done or irq_detect or cpuoff or cpu_halt_cmd or e_state)
|
irq_detect or cpuoff or cpu_halt_cmd or e_state)
|
case(i_state)
|
case(i_state)
|
I_IDLE : i_state_nxt = (irq_detect & ~cpu_halt_cmd) ? I_IRQ_FETCH :
|
I_IDLE : i_state_nxt = (irq_detect & ~cpu_halt_cmd) ? I_IRQ_FETCH :
|
(~cpuoff & ~cpu_halt_cmd) ? I_DEC : I_IDLE;
|
(~cpuoff & ~cpu_halt_cmd) ? I_DEC : I_IDLE;
|
I_IRQ_FETCH: i_state_nxt = I_IRQ_DONE;
|
I_IRQ_FETCH: i_state_nxt = I_IRQ_DONE;
|
I_IRQ_DONE : i_state_nxt = I_DEC;
|
I_IRQ_DONE : i_state_nxt = I_DEC;
|
I_DEC : i_state_nxt = irq_detect ? I_IRQ_FETCH :
|
I_DEC : i_state_nxt = irq_detect ? I_IRQ_FETCH :
|
(cpuoff | cpu_halt_cmd) & exec_done ? I_IDLE :
|
(cpuoff | cpu_halt_cmd) & exec_done ? I_IDLE :
|
cpu_halt_cmd & (e_state==`E_IDLE) ? I_IDLE :
|
cpu_halt_cmd & (e_state==E_IDLE) ? I_IDLE :
|
pc_sw_wr ? I_DEC :
|
pc_sw_wr ? I_DEC :
|
~exec_done & ~(e_state==`E_IDLE) ? I_DEC : // Wait in decode state
|
~exec_done & ~(e_state==E_IDLE) ? I_DEC : // Wait in decode state
|
(inst_sz_nxt!=2'b00) ? I_EXT1 : I_DEC; // until execution is completed
|
(inst_sz_nxt!=2'b00) ? I_EXT1 : I_DEC; // until execution is completed
|
I_EXT1 : i_state_nxt = irq_detect ? I_IRQ_FETCH :
|
I_EXT1 : i_state_nxt = irq_detect ? I_IRQ_FETCH :
|
pc_sw_wr ? I_DEC :
|
pc_sw_wr ? I_DEC :
|
(inst_sz!=2'b01) ? I_EXT2 : I_DEC;
|
(inst_sz!=2'b01) ? I_EXT2 : I_DEC;
|
I_EXT2 : i_state_nxt = irq_detect ? I_IRQ_FETCH : I_DEC;
|
I_EXT2 : i_state_nxt = irq_detect ? I_IRQ_FETCH : I_DEC;
|
default : i_state_nxt = I_IRQ_FETCH;
|
default : i_state_nxt = I_IRQ_FETCH;
|
endcase
|
endcase
|
|
|
// State machine
|
// State machine
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) i_state <= I_IRQ_FETCH;
|
if (puc_rst) i_state <= I_IRQ_FETCH;
|
else i_state <= i_state_nxt;
|
else i_state <= i_state_nxt;
|
|
|
// Utility signals
|
// Utility signals
|
wire decode_noirq = ((i_state==I_DEC) & (exec_done | (e_state==`E_IDLE)));
|
wire decode_noirq = ((i_state==I_DEC) & (exec_done | (e_state==E_IDLE)));
|
wire decode = decode_noirq | irq_detect;
|
wire decode = decode_noirq | irq_detect;
|
wire fetch = ~((i_state==I_DEC) & ~(exec_done | (e_state==`E_IDLE))) & ~(e_state_nxt==`E_IDLE);
|
wire fetch = ~((i_state==I_DEC) & ~(exec_done | (e_state==E_IDLE))) & ~(e_state_nxt==E_IDLE);
|
|
|
// Debug interface cpu status
|
// Debug interface cpu status
|
reg dbg_halt_st;
|
reg dbg_halt_st;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) dbg_halt_st <= 1'b0;
|
if (puc_rst) dbg_halt_st <= 1'b0;
|
else dbg_halt_st <= cpu_halt_cmd & (i_state_nxt==I_IDLE);
|
else dbg_halt_st <= cpu_halt_cmd & (i_state_nxt==I_IDLE);
|
|
|
|
|
//=============================================================================
|
//=============================================================================
|
// 2) INTERRUPT HANDLING
|
// 4) INTERRUPT HANDLING
|
//=============================================================================
|
//=============================================================================
|
|
|
// Detect nmi interrupt
|
// Detect nmi interrupt
|
reg inst_nmi;
|
reg inst_nmi;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_nmi <= 1'b0;
|
if (puc_rst) inst_nmi <= 1'b0;
|
else if (nmi_evt) inst_nmi <= 1'b1;
|
else if (nmi_evt) inst_nmi <= 1'b1;
|
else if (i_state==I_IRQ_DONE) inst_nmi <= 1'b0;
|
else if (i_state==I_IRQ_DONE) inst_nmi <= 1'b0;
|
|
|
|
|
// Detect reset interrupt
|
// Detect reset interrupt
|
reg inst_irq_rst;
|
reg inst_irq_rst;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_irq_rst <= 1'b1;
|
if (puc_rst) inst_irq_rst <= 1'b1;
|
else if (exec_done) inst_irq_rst <= 1'b0;
|
else if (exec_done) inst_irq_rst <= 1'b0;
|
|
|
// Detect other interrupts
|
// Detect other interrupts
|
assign irq_detect = (inst_nmi | ((|irq | wdt_irq) & gie)) & ~cpu_halt_cmd & ~dbg_halt_st & (exec_done | (i_state==I_IDLE));
|
assign irq_detect = (inst_nmi | ((|irq | wdt_irq) & gie)) & ~cpu_halt_cmd & ~dbg_halt_st & (exec_done | (i_state==I_IDLE));
|
|
|
// Select interrupt vector
|
// Select interrupt vector
|
reg [3:0] irq_num;
|
reg [3:0] irq_num;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) irq_num <= 4'hf;
|
if (puc_rst) irq_num <= 4'hf;
|
else if (irq_detect) irq_num <= inst_nmi ? 4'he :
|
else if (irq_detect) irq_num <= inst_nmi ? 4'he :
|
irq[13] ? 4'hd :
|
irq[13] ? 4'hd :
|
irq[12] ? 4'hc :
|
irq[12] ? 4'hc :
|
irq[11] ? 4'hb :
|
irq[11] ? 4'hb :
|
(irq[10] | wdt_irq) ? 4'ha :
|
(irq[10] | wdt_irq) ? 4'ha :
|
Line 264... |
Line 291... |
wire [13:0] irq_acc = irq_acc_all[13:0];
|
wire [13:0] irq_acc = irq_acc_all[13:0];
|
wire nmi_acc = irq_acc_all[14];
|
wire nmi_acc = irq_acc_all[14];
|
|
|
|
|
//=============================================================================
|
//=============================================================================
|
// 3) FETCH INSTRUCTION
|
// 5) FETCH INSTRUCTION
|
//=============================================================================
|
//=============================================================================
|
|
|
//
|
//
|
// 3.1) PROGRAM COUNTER & MEMORY INTERFACE
|
// 5.1) PROGRAM COUNTER & MEMORY INTERFACE
|
//-----------------------------------------
|
//-----------------------------------------
|
|
|
// Program counter
|
// Program counter
|
reg [15:0] pc;
|
reg [15:0] pc;
|
|
|
Line 280... |
Line 307... |
wire [15:0] pc_incr = pc + {14'h0000, fetch, 1'b0};
|
wire [15:0] pc_incr = pc + {14'h0000, fetch, 1'b0};
|
wire [15:0] pc_nxt = pc_sw_wr ? pc_sw :
|
wire [15:0] pc_nxt = pc_sw_wr ? pc_sw :
|
(i_state==I_IRQ_FETCH) ? irq_addr :
|
(i_state==I_IRQ_FETCH) ? irq_addr :
|
(i_state==I_IRQ_DONE) ? mdb_in : pc_incr;
|
(i_state==I_IRQ_DONE) ? mdb_in : pc_incr;
|
|
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) pc <= 16'h0000;
|
if (puc_rst) pc <= 16'h0000;
|
else pc <= pc_nxt;
|
else pc <= pc_nxt;
|
|
|
// Check if ROM has been busy in order to retry ROM access
|
// Check if ROM has been busy in order to retry ROM access
|
reg pmem_busy;
|
reg pmem_busy;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) pmem_busy <= 1'b0;
|
if (puc_rst) pmem_busy <= 1'b0;
|
else pmem_busy <= fe_pmem_wait;
|
else pmem_busy <= fe_pmem_wait;
|
|
|
// Memory interface
|
// Memory interface
|
wire [15:0] mab = pc_nxt;
|
wire [15:0] mab = pc_nxt;
|
wire mb_en = fetch | pc_sw_wr | (i_state==I_IRQ_FETCH) | pmem_busy | (dbg_halt_st & ~cpu_halt_cmd);
|
wire mb_en = fetch | pc_sw_wr | (i_state==I_IRQ_FETCH) | pmem_busy | (dbg_halt_st & ~cpu_halt_cmd);
|
|
|
|
|
//
|
//
|
// 3.2) INSTRUCTION REGISTER
|
// 5.2) INSTRUCTION REGISTER
|
//--------------------------------
|
//--------------------------------
|
|
|
// Instruction register
|
// Instruction register
|
wire [15:0] ir = mdb_in;
|
wire [15:0] ir = mdb_in;
|
|
|
Line 319... |
Line 346... |
|
|
wire [15:0] ext_nxt = ir + ext_incr;
|
wire [15:0] ext_nxt = ir + ext_incr;
|
|
|
// Store source extension word
|
// Store source extension word
|
reg [15:0] inst_sext;
|
reg [15:0] inst_sext;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_sext <= 16'h0000;
|
if (puc_rst) inst_sext <= 16'h0000;
|
else if (decode & is_const) inst_sext <= sconst_nxt;
|
else if (decode & is_const) inst_sext <= sconst_nxt;
|
else if (decode & inst_type_nxt[`INST_JMP]) inst_sext <= {{5{ir[9]}},ir[9:0],1'b0};
|
else if (decode & inst_type_nxt[`INST_JMP]) inst_sext <= {{5{ir[9]}},ir[9:0],1'b0};
|
else if ((i_state==I_EXT1) & is_sext) inst_sext <= ext_nxt;
|
else if ((i_state==I_EXT1) & is_sext) inst_sext <= ext_nxt;
|
|
|
// Source extension word is ready
|
// Source extension word is ready
|
wire inst_sext_rdy = (i_state==I_EXT1) & is_sext;
|
wire inst_sext_rdy = (i_state==I_EXT1) & is_sext;
|
|
|
|
|
// Store destination extension word
|
// Store destination extension word
|
reg [15:0] inst_dext;
|
reg [15:0] inst_dext;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_dext <= 16'h0000;
|
if (puc_rst) inst_dext <= 16'h0000;
|
else if ((i_state==I_EXT1) & ~is_sext) inst_dext <= ext_nxt;
|
else if ((i_state==I_EXT1) & ~is_sext) inst_dext <= ext_nxt;
|
else if (i_state==I_EXT2) inst_dext <= ext_nxt;
|
else if (i_state==I_EXT2) inst_dext <= ext_nxt;
|
|
|
// Destination extension word is ready
|
// Destination extension word is ready
|
wire inst_dext_rdy = (((i_state==I_EXT1) & ~is_sext) | (i_state==I_EXT2));
|
wire inst_dext_rdy = (((i_state==I_EXT1) & ~is_sext) | (i_state==I_EXT2));
|
|
|
|
|
//=============================================================================
|
//=============================================================================
|
// 4) DECODE INSTRUCTION
|
// 6) DECODE INSTRUCTION
|
//=============================================================================
|
//=============================================================================
|
|
|
//
|
//
|
// 4.1) OPCODE: INSTRUCTION TYPE
|
// 6.1) OPCODE: INSTRUCTION TYPE
|
//----------------------------------------
|
//----------------------------------------
|
// Instructions type is encoded in a one hot fashion as following:
|
// Instructions type is encoded in a one hot fashion as following:
|
//
|
//
|
// 3'b001: Single-operand arithmetic
|
// 3'b001: Single-operand arithmetic
|
// 3'b010: Conditional jump
|
// 3'b010: Conditional jump
|
Line 358... |
Line 385... |
reg [2:0] inst_type;
|
reg [2:0] inst_type;
|
assign inst_type_nxt = {(ir[15:14]!=2'b00),
|
assign inst_type_nxt = {(ir[15:14]!=2'b00),
|
(ir[15:13]==3'b001),
|
(ir[15:13]==3'b001),
|
(ir[15:13]==3'b000)} & {3{~irq_detect}};
|
(ir[15:13]==3'b000)} & {3{~irq_detect}};
|
|
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_type <= 3'b000;
|
if (puc_rst) inst_type <= 3'b000;
|
else if (decode) inst_type <= inst_type_nxt;
|
else if (decode) inst_type <= inst_type_nxt;
|
|
|
//
|
//
|
// 4.2) OPCODE: SINGLE-OPERAND ARITHMETIC
|
// 6.2) OPCODE: SINGLE-OPERAND ARITHMETIC
|
//----------------------------------------
|
//----------------------------------------
|
// Instructions are encoded in a one hot fashion as following:
|
// Instructions are encoded in a one hot fashion as following:
|
//
|
//
|
// 8'b00000001: RRC
|
// 8'b00000001: RRC
|
// 8'b00000010: SWPB
|
// 8'b00000010: SWPB
|
Line 379... |
Line 406... |
// 8'b10000000: IRQ
|
// 8'b10000000: IRQ
|
|
|
reg [7:0] inst_so;
|
reg [7:0] inst_so;
|
wire [7:0] inst_so_nxt = irq_detect ? 8'h80 : (one_hot8(ir[9:7]) & {8{inst_type_nxt[`INST_SO]}});
|
wire [7:0] inst_so_nxt = irq_detect ? 8'h80 : (one_hot8(ir[9:7]) & {8{inst_type_nxt[`INST_SO]}});
|
|
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_so <= 8'h00;
|
if (puc_rst) inst_so <= 8'h00;
|
else if (decode) inst_so <= inst_so_nxt;
|
else if (decode) inst_so <= inst_so_nxt;
|
|
|
//
|
//
|
// 4.3) OPCODE: CONDITIONAL JUMP
|
// 6.3) OPCODE: CONDITIONAL JUMP
|
//--------------------------------
|
//--------------------------------
|
// Instructions are encoded in a one hot fashion as following:
|
// Instructions are encoded in a one hot fashion as following:
|
//
|
//
|
// 8'b00000001: JNE/JNZ
|
// 8'b00000001: JNE/JNZ
|
// 8'b00000010: JEQ/JZ
|
// 8'b00000010: JEQ/JZ
|
Line 398... |
Line 425... |
// 8'b00100000: JGE
|
// 8'b00100000: JGE
|
// 8'b01000000: JL
|
// 8'b01000000: JL
|
// 8'b10000000: JMP
|
// 8'b10000000: JMP
|
|
|
reg [2:0] inst_jmp_bin;
|
reg [2:0] inst_jmp_bin;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_jmp_bin <= 3'h0;
|
if (puc_rst) inst_jmp_bin <= 3'h0;
|
else if (decode) inst_jmp_bin <= ir[12:10];
|
else if (decode) inst_jmp_bin <= ir[12:10];
|
|
|
wire [7:0] inst_jmp = one_hot8(inst_jmp_bin) & {8{inst_type[`INST_JMP]}};
|
wire [7:0] inst_jmp = one_hot8(inst_jmp_bin) & {8{inst_type[`INST_JMP]}};
|
|
|
|
|
//
|
//
|
// 4.4) OPCODE: TWO-OPERAND ARITHMETIC
|
// 6.4) OPCODE: TWO-OPERAND ARITHMETIC
|
//-------------------------------------
|
//-------------------------------------
|
// Instructions are encoded in a one hot fashion as following:
|
// Instructions are encoded in a one hot fashion as following:
|
//
|
//
|
// 12'b000000000001: MOV
|
// 12'b000000000001: MOV
|
// 12'b000000000010: ADD
|
// 12'b000000000010: ADD
|
Line 427... |
Line 454... |
|
|
wire [15:0] inst_to_1hot = one_hot16(ir[15:12]) & {16{inst_type_nxt[`INST_TO]}};
|
wire [15:0] inst_to_1hot = one_hot16(ir[15:12]) & {16{inst_type_nxt[`INST_TO]}};
|
wire [11:0] inst_to_nxt = inst_to_1hot[15:4];
|
wire [11:0] inst_to_nxt = inst_to_1hot[15:4];
|
|
|
reg inst_mov;
|
reg inst_mov;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_mov <= 1'b0;
|
if (puc_rst) inst_mov <= 1'b0;
|
else if (decode) inst_mov <= inst_to_nxt[`MOV];
|
else if (decode) inst_mov <= inst_to_nxt[`MOV];
|
|
|
|
|
//
|
//
|
// 4.5) SOURCE AND DESTINATION REGISTERS
|
// 6.5) SOURCE AND DESTINATION REGISTERS
|
//---------------------------------------
|
//---------------------------------------
|
|
|
// Destination register
|
// Destination register
|
reg [3:0] inst_dest_bin;
|
reg [3:0] inst_dest_bin;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_dest_bin <= 4'h0;
|
if (puc_rst) inst_dest_bin <= 4'h0;
|
else if (decode) inst_dest_bin <= ir[3:0];
|
else if (decode) inst_dest_bin <= ir[3:0];
|
|
|
wire [15:0] inst_dest = dbg_halt_st ? one_hot16(dbg_reg_sel) :
|
wire [15:0] inst_dest = dbg_halt_st ? one_hot16(dbg_reg_sel) :
|
inst_type[`INST_JMP] ? 16'h0001 :
|
inst_type[`INST_JMP] ? 16'h0001 :
|
inst_so[`IRQ] |
|
inst_so[`IRQ] |
|
Line 452... |
Line 479... |
one_hot16(inst_dest_bin);
|
one_hot16(inst_dest_bin);
|
|
|
|
|
// Source register
|
// Source register
|
reg [3:0] inst_src_bin;
|
reg [3:0] inst_src_bin;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_src_bin <= 4'h0;
|
if (puc_rst) inst_src_bin <= 4'h0;
|
else if (decode) inst_src_bin <= ir[11:8];
|
else if (decode) inst_src_bin <= ir[11:8];
|
|
|
wire [15:0] inst_src = inst_type[`INST_TO] ? one_hot16(inst_src_bin) :
|
wire [15:0] inst_src = inst_type[`INST_TO] ? one_hot16(inst_src_bin) :
|
inst_so[`RETI] ? 16'h0002 :
|
inst_so[`RETI] ? 16'h0002 :
|
inst_so[`IRQ] ? 16'h0001 :
|
inst_so[`IRQ] ? 16'h0001 :
|
inst_type[`INST_SO] ? one_hot16(inst_dest_bin) : 16'h0000;
|
inst_type[`INST_SO] ? one_hot16(inst_dest_bin) : 16'h0000;
|
|
|
|
|
//
|
//
|
// 4.6) SOURCE ADDRESSING MODES
|
// 6.6) SOURCE ADDRESSING MODES
|
//--------------------------------
|
//--------------------------------
|
// Source addressing modes are encoded in a one hot fashion as following:
|
// Source addressing modes are encoded in a one hot fashion as following:
|
//
|
//
|
// 13'b0000000000001: Register direct.
|
// 13'b0000000000001: Register direct.
|
// 13'b0000000000010: Register indexed.
|
// 13'b0000000000010: Register indexed.
|
Line 521... |
Line 548... |
endcase
|
endcase
|
end
|
end
|
assign is_const = |inst_as_nxt[12:7];
|
assign is_const = |inst_as_nxt[12:7];
|
|
|
reg [7:0] inst_as;
|
reg [7:0] inst_as;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_as <= 8'h00;
|
if (puc_rst) inst_as <= 8'h00;
|
else if (decode) inst_as <= {is_const, inst_as_nxt[6:0]};
|
else if (decode) inst_as <= {is_const, inst_as_nxt[6:0]};
|
|
|
|
|
// 13'b0000010000000: Constant 4.
|
// 13'b0000010000000: Constant 4.
|
// 13'b0000100000000: Constant 8.
|
// 13'b0000100000000: Constant 8.
|
Line 545... |
Line 572... |
else sconst_nxt = 16'h0000;
|
else sconst_nxt = 16'h0000;
|
end
|
end
|
|
|
|
|
//
|
//
|
// 4.7) DESTINATION ADDRESSING MODES
|
// 6.7) DESTINATION ADDRESSING MODES
|
//-----------------------------------
|
//-----------------------------------
|
// Destination addressing modes are encoded in a one hot fashion as following:
|
// Destination addressing modes are encoded in a one hot fashion as following:
|
//
|
//
|
// 8'b00000001: Register direct.
|
// 8'b00000001: Register direct.
|
// 8'b00000010: Register indexed.
|
// 8'b00000010: Register indexed.
|
Line 580... |
Line 607... |
default: inst_ad_nxt = 8'b00000001;
|
default: inst_ad_nxt = 8'b00000001;
|
endcase
|
endcase
|
end
|
end
|
|
|
reg [7:0] inst_ad;
|
reg [7:0] inst_ad;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_ad <= 8'h00;
|
if (puc_rst) inst_ad <= 8'h00;
|
else if (decode) inst_ad <= inst_ad_nxt;
|
else if (decode) inst_ad <= inst_ad_nxt;
|
|
|
|
|
//
|
//
|
// 4.8) REMAINING INSTRUCTION DECODING
|
// 6.8) REMAINING INSTRUCTION DECODING
|
//-------------------------------------
|
//-------------------------------------
|
|
|
// Operation size
|
// Operation size
|
reg inst_bw;
|
reg inst_bw;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_bw <= 1'b0;
|
if (puc_rst) inst_bw <= 1'b0;
|
else if (decode) inst_bw <= ir[6] & ~inst_type_nxt[`INST_JMP] & ~irq_detect & ~cpu_halt_cmd;
|
else if (decode) inst_bw <= ir[6] & ~inst_type_nxt[`INST_JMP] & ~irq_detect & ~cpu_halt_cmd;
|
|
|
// Extended instruction size
|
// Extended instruction size
|
assign inst_sz_nxt = {1'b0, (inst_as_nxt[`IDX] | inst_as_nxt[`SYMB] | inst_as_nxt[`ABS] | inst_as_nxt[`IMM])} +
|
assign inst_sz_nxt = {1'b0, (inst_as_nxt[`IDX] | inst_as_nxt[`SYMB] | inst_as_nxt[`ABS] | inst_as_nxt[`IMM])} +
|
{1'b0, ((inst_ad_nxt[`IDX] | inst_ad_nxt[`SYMB] | inst_ad_nxt[`ABS]) & ~inst_type_nxt[`INST_SO])};
|
{1'b0, ((inst_ad_nxt[`IDX] | inst_ad_nxt[`SYMB] | inst_ad_nxt[`ABS]) & ~inst_type_nxt[`INST_SO])};
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_sz <= 2'b00;
|
if (puc_rst) inst_sz <= 2'b00;
|
else if (decode) inst_sz <= inst_sz_nxt;
|
else if (decode) inst_sz <= inst_sz_nxt;
|
|
|
|
|
//=============================================================================
|
//=============================================================================
|
// 5) EXECUTION-UNIT STATE MACHINE
|
// 7) EXECUTION-UNIT STATE MACHINE
|
//=============================================================================
|
//=============================================================================
|
|
|
// State machine registers
|
// State machine registers
|
reg [3:0] e_state;
|
reg [3:0] e_state;
|
|
|
Line 624... |
Line 651... |
wire dst_rd = inst_ad[`IDX] | inst_so[`PUSH] | inst_so[`CALL] | inst_so[`RETI];
|
wire dst_rd = inst_ad[`IDX] | inst_so[`PUSH] | inst_so[`CALL] | inst_so[`RETI];
|
|
|
wire inst_branch = (inst_ad_nxt[`DIR] & (ir[3:0]==4'h0)) | inst_type_nxt[`INST_JMP] | inst_so_nxt[`RETI];
|
wire inst_branch = (inst_ad_nxt[`DIR] & (ir[3:0]==4'h0)) | inst_type_nxt[`INST_JMP] | inst_so_nxt[`RETI];
|
|
|
reg exec_jmp;
|
reg exec_jmp;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) exec_jmp <= 1'b0;
|
if (puc_rst) exec_jmp <= 1'b0;
|
else if (inst_branch & decode) exec_jmp <= 1'b1;
|
else if (inst_branch & decode) exec_jmp <= 1'b1;
|
else if (e_state==`E_JUMP) exec_jmp <= 1'b0;
|
else if (e_state==E_JUMP) exec_jmp <= 1'b0;
|
|
|
reg exec_dst_wr;
|
reg exec_dst_wr;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) exec_dst_wr <= 1'b0;
|
if (puc_rst) exec_dst_wr <= 1'b0;
|
else if (e_state==`E_DST_RD) exec_dst_wr <= 1'b1;
|
else if (e_state==E_DST_RD) exec_dst_wr <= 1'b1;
|
else if (e_state==`E_DST_WR) exec_dst_wr <= 1'b0;
|
else if (e_state==E_DST_WR) exec_dst_wr <= 1'b0;
|
|
|
reg exec_src_wr;
|
reg exec_src_wr;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) exec_src_wr <= 1'b0;
|
if (puc_rst) exec_src_wr <= 1'b0;
|
else if (inst_type[`INST_SO] & (e_state==`E_SRC_RD)) exec_src_wr <= 1'b1;
|
else if (inst_type[`INST_SO] & (e_state==E_SRC_RD)) exec_src_wr <= 1'b1;
|
else if ((e_state==`E_SRC_WR) || (e_state==`E_DST_WR)) exec_src_wr <= 1'b0;
|
else if ((e_state==E_SRC_WR) || (e_state==E_DST_WR)) exec_src_wr <= 1'b0;
|
|
|
reg exec_dext_rdy;
|
reg exec_dext_rdy;
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) exec_dext_rdy <= 1'b0;
|
if (puc_rst) exec_dext_rdy <= 1'b0;
|
else if (e_state==`E_DST_RD) exec_dext_rdy <= 1'b0;
|
else if (e_state==E_DST_RD) exec_dext_rdy <= 1'b0;
|
else if (inst_dext_rdy) exec_dext_rdy <= 1'b1;
|
else if (inst_dext_rdy) exec_dext_rdy <= 1'b1;
|
|
|
// Execution first state
|
// Execution first state
|
wire [3:0] e_first_state = ~dbg_halt_st & inst_so_nxt[`IRQ] ? `E_IRQ_0 :
|
wire [3:0] e_first_state = ~dbg_halt_st & inst_so_nxt[`IRQ] ? E_IRQ_0 :
|
cpu_halt_cmd | (i_state==I_IDLE) ? `E_IDLE :
|
cpu_halt_cmd | (i_state==I_IDLE) ? E_IDLE :
|
cpuoff ? `E_IDLE :
|
cpuoff ? E_IDLE :
|
src_acalc_pre ? `E_SRC_AD :
|
src_acalc_pre ? E_SRC_AD :
|
src_rd_pre ? `E_SRC_RD :
|
src_rd_pre ? E_SRC_RD :
|
dst_acalc_pre ? `E_DST_AD :
|
dst_acalc_pre ? E_DST_AD :
|
dst_rd_pre ? `E_DST_RD : `E_EXEC;
|
dst_rd_pre ? E_DST_RD : E_EXEC;
|
|
|
|
|
// State machine
|
// State machine
|
//--------------------------------
|
//--------------------------------
|
|
|
// States Transitions
|
// States Transitions
|
always @(e_state or dst_acalc or dst_rd or inst_sext_rdy or
|
always @(e_state or dst_acalc or dst_rd or inst_sext_rdy or
|
inst_dext_rdy or exec_dext_rdy or exec_jmp or exec_dst_wr or
|
inst_dext_rdy or exec_dext_rdy or exec_jmp or exec_dst_wr or
|
e_first_state or exec_src_wr)
|
e_first_state or exec_src_wr)
|
case(e_state)
|
case(e_state)
|
`E_IDLE : e_state_nxt = e_first_state;
|
E_IDLE : e_state_nxt = e_first_state;
|
`E_IRQ_0 : e_state_nxt = `E_IRQ_1;
|
E_IRQ_0 : e_state_nxt = E_IRQ_1;
|
`E_IRQ_1 : e_state_nxt = `E_IRQ_2;
|
E_IRQ_1 : e_state_nxt = E_IRQ_2;
|
`E_IRQ_2 : e_state_nxt = `E_IRQ_3;
|
E_IRQ_2 : e_state_nxt = E_IRQ_3;
|
`E_IRQ_3 : e_state_nxt = `E_IRQ_4;
|
E_IRQ_3 : e_state_nxt = E_IRQ_4;
|
`E_IRQ_4 : e_state_nxt = `E_EXEC;
|
E_IRQ_4 : e_state_nxt = E_EXEC;
|
|
|
`E_SRC_AD : e_state_nxt = inst_sext_rdy ? `E_SRC_RD : `E_SRC_AD;
|
E_SRC_AD : e_state_nxt = inst_sext_rdy ? E_SRC_RD : E_SRC_AD;
|
|
|
`E_SRC_RD : e_state_nxt = dst_acalc ? `E_DST_AD :
|
E_SRC_RD : e_state_nxt = dst_acalc ? E_DST_AD :
|
dst_rd ? `E_DST_RD : `E_EXEC;
|
dst_rd ? E_DST_RD : E_EXEC;
|
|
|
`E_DST_AD : e_state_nxt = (inst_dext_rdy |
|
E_DST_AD : e_state_nxt = (inst_dext_rdy |
|
exec_dext_rdy) ? `E_DST_RD : `E_DST_AD;
|
exec_dext_rdy) ? E_DST_RD : E_DST_AD;
|
|
|
`E_DST_RD : e_state_nxt = `E_EXEC;
|
E_DST_RD : e_state_nxt = E_EXEC;
|
|
|
`E_EXEC : e_state_nxt = exec_dst_wr ? `E_DST_WR :
|
E_EXEC : e_state_nxt = exec_dst_wr ? E_DST_WR :
|
exec_jmp ? `E_JUMP :
|
exec_jmp ? E_JUMP :
|
exec_src_wr ? `E_SRC_WR : e_first_state;
|
exec_src_wr ? E_SRC_WR : e_first_state;
|
|
|
`E_JUMP : e_state_nxt = e_first_state;
|
E_JUMP : e_state_nxt = e_first_state;
|
`E_DST_WR : e_state_nxt = exec_jmp ? `E_JUMP : e_first_state;
|
E_DST_WR : e_state_nxt = exec_jmp ? E_JUMP : e_first_state;
|
`E_SRC_WR : e_state_nxt = e_first_state;
|
E_SRC_WR : e_state_nxt = e_first_state;
|
default : e_state_nxt = `E_IRQ_0;
|
default : e_state_nxt = E_IRQ_0;
|
endcase
|
endcase
|
|
|
// State machine
|
// State machine
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) e_state <= `E_IRQ_1;
|
if (puc_rst) e_state <= E_IRQ_1;
|
else e_state <= e_state_nxt;
|
else e_state <= e_state_nxt;
|
|
|
|
|
// Frontend State machine control signals
|
// Frontend State machine control signals
|
//----------------------------------------
|
//----------------------------------------
|
|
|
wire exec_done = exec_jmp ? (e_state==`E_JUMP) :
|
wire exec_done = exec_jmp ? (e_state==E_JUMP) :
|
exec_dst_wr ? (e_state==`E_DST_WR) :
|
exec_dst_wr ? (e_state==E_DST_WR) :
|
exec_src_wr ? (e_state==`E_SRC_WR) : (e_state==`E_EXEC);
|
exec_src_wr ? (e_state==E_SRC_WR) : (e_state==E_EXEC);
|
|
|
|
|
//=============================================================================
|
//=============================================================================
|
// 6) EXECUTION-UNIT STATE CONTROL
|
// 8) EXECUTION-UNIT STATE CONTROL
|
//=============================================================================
|
//=============================================================================
|
|
|
//
|
//
|
// 6.1) ALU CONTROL SIGNALS
|
// 8.1) ALU CONTROL SIGNALS
|
//-------------------------------------
|
//-------------------------------------
|
//
|
//
|
// 12'b000000000001: Enable ALU source inverter
|
// 12'b000000000001: Enable ALU source inverter
|
// 12'b000000000010: Enable Incrementer
|
// 12'b000000000010: Enable Incrementer
|
// 12'b000000000100: Enable Incrementer on carry bit
|
// 12'b000000000100: Enable Incrementer on carry bit
|
Line 767... |
Line 794... |
|
|
wire alu_shift = inst_so_nxt[`RRC] | inst_so_nxt[`RRA];
|
wire alu_shift = inst_so_nxt[`RRC] | inst_so_nxt[`RRA];
|
|
|
wire exec_no_wr = inst_to_nxt[`CMP] | inst_to_nxt[`BIT];
|
wire exec_no_wr = inst_to_nxt[`CMP] | inst_to_nxt[`BIT];
|
|
|
always @(posedge mclk or posedge puc)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc) inst_alu <= 12'h000;
|
if (puc_rst) inst_alu <= 12'h000;
|
else if (decode) inst_alu <= {exec_no_wr,
|
else if (decode) inst_alu <= {exec_no_wr,
|
alu_shift,
|
alu_shift,
|
alu_stat_f,
|
alu_stat_f,
|
alu_stat_7,
|
alu_stat_7,
|
alu_dadd,
|
alu_dadd,
|