📄 sequencer.v
字号:
if ((reg_opl[7:6]==2'b10)&&(reg_opl[2:0]==3'b111)) begin
alu_func <= 4'b1000;
case (reg_opl[5:3]) // latch the dest reg on s0
3'b000: w_acc_gate <= 1'b0;
3'b001: w_ax_gate <= 1'b0;
3'b010: w_bx_gate <= 1'b0;
3'b101: w_p_gate <= 1'b0;
default: dummy <= 1'b0; //do nothing
endcase
bbus_mux <= 3'b110;
w_pc_gate <= 1'b0; // increment pc on s0
code_cs_l <= 1'b0; // allow -cs and -rd to code ram
code_rd_l_gate <= 1'b0;
w_oplo_gate <= 1'b0; // assert oplo gate
next_state <= state_s0;
end
// ALU op - immediate
else if ((reg_opl[7:6]==2'b00)&&(reg_opl[2:0]==3'b111)) begin
alu_func <= reg_opl[6:3]; // get alu oprerationg from instruction
w_acc_gate <= 1'b0; // latch acc on s0
w_flag_gate <= 1'b0; // update flag on s0
bbus_mux <= 3'b110;
w_pc_gate <= 1'b0; // increment pc on s0
code_cs_l <= 1'b0; // allow -cs and -rd to code ram
code_rd_l_gate <= 1'b0;
w_oplo_gate <= 1'b0; // assert oplo gate
next_state <= state_s0;
end
// CMPACC op - immediate
else if ((reg_opl[7:3]==5'b01000)&&(reg_opl[2:0]==3'b111)) begin
alu_func <= 4'b001; // alu to subtract
w_flag_gate <= 1'b0; // update flag on s0
bbus_mux <= 3'b110; // bbus select d_bus
w_pc_gate <= 1'b0; // increment pc on s0
code_cs_l <= 1'b0; // allow -cs and -rd to code ram
code_rd_l_gate <= 1'b0;
w_oplo_gate <= 1'b0; // assert oplo gate
next_state <= state_s0;
end
// POP, part II, load data from [SP]
else if (reg_opl[7:3]==5'b01111) begin
code_cs_l <= 1'b1; // don't read from code ram
alu_func <= 4'b1000; // c_bus = b_bus
bbus_mux <= 3'b110; // b_bus = d_bus
w_sp_gate <= 1'b1; // disallow sp to change
addx_mux <= 2'b10; // select sp as addx source
sram_cs_l <= 1'b0; // select sram
code_rd_l_gate <= 1'b0; // and read
w_oplo_gate <= 1'b0; // and latch it into reg_oplo
case (reg_opl[2:0])
3'b000: w_acc_gate <= 1'b0;
3'b001: w_ax_gate <= 1'b0;
3'b010: w_bx_gate <= 1'b0;
3'b100: begin
w_flag_gate <= 1'b0;
flag_mux <= 1'b0;
end
default: w_p_gate <= 1'b0;
endcase
w_pc_gate <= 1'b0; // increment pc on s0
next_state <= state_s0;
end
// RET, part II, load hi byte of saved PC
else if (reg_opl[7:0]==8'b11011110) begin
code_cs_l <= 1'b1; // don't read from code ram
alu_func <= 4'b1000; // c_bus = b_bus
bbus_mux <= 3'b110; // b_bus = d_bus
sp_mux <= 1'b0; // increment SP
w_sp_gate <= 1'b0; // allow sp to change
addx_mux <= 2'b10; // select sp as addx source
sram_cs_l <= 1'b0; // select sram
code_rd_l_gate <= 1'b0; // and read
w_ophi_gate <= 1'b0; // and latch it into reg_ophi
code_rd_l_gate <= 1'b0;
w_oplo_gate <= 1'b0; // assert oplo gate
next_state <= state_s3;
end
// these are the 3 byte branching instructions. so go and fetch the high
// byte operand
else begin
code_cs_l <= 1'b0; // allow -cs and -rd to code ram
code_rd_l_gate <= 1'b0;
alu_func <= 4'b1000;
w_acc_gate <= 1'b1;
w_ax_gate <= 1'b1;
w_bx_gate <= 1'b1;
w_p_gate <= 1'b1;
bbus_mux <= 3'b110;
pc_mux <= 1'b1;
w_pc_gate <= 1'b0; // increment pc on s3
w_oplo_gate <= 1'b0; // assert oplo gate
next_state <= state_s3;
end
end
/*
** BRANCHING INSTRUCTIONS, 3 bytes, 4 cycles
*/
state_s3: begin
// w_ophi_gate <= 1'b0; // latch-in high byte operand
// w_oplo_gate <= 1'b1; // deassert oplo gate
// Branching operations - immediate
if((reg_opl[7]==1'b1)&&(reg_opl[2:0]==3'b000)) begin
alu_func <= 4'b1000; // for debug, c_bus=b_bus
bbus_mux <= 3'b110; // for debug c_bus=d_bus
case(reg_opl[6:3])
4'b0011: if(reg_flag[0]==1'b1) // JE
pc_mux<=0;
else pc_mux<=1;
4'b0100: if(reg_flag[0]==1'b0) // JNE
pc_mux<=0;
else pc_mux<=1;
4'b0101: if(reg_flag[1]==1'b1) // JP
pc_mux<=0;
else pc_mux<=1;
4'b0110: if(reg_flag[1]==1'b0) // JN
pc_mux<=0;
else pc_mux<=1;
4'b0111: if(reg_flag[2]==1'b1) // JC
pc_mux<=0;
else pc_mux<=1;
4'b1000: if(reg_flag[2]==1'b0) // JNC
pc_mux<=0;
else pc_mux<=1;
4'b1001: pc_mux<=0; // JMP unconditional
default: pc_mux<=pc_mux;
endcase
w_pc_gate <= 1'b0; // increment pc on s0
w_ophi_gate <= 1'b0; // latch-in high byte operand
w_oplo_gate <= 1'b1; // deassert oplo gate
next_state <= state_s0;
end
// RET, part III, load lo byte of saved PC
else if (reg_opl[7:0]==8'b11011110) begin
code_cs_l <= 1'b1; // don't read from code ram
alu_func <= 4'b1000; // c_bus = b_bus
bbus_mux <= 3'b100; // b_bus = reg_pc hi
sp_mux <= 1'b1; // increment SP
w_sp_gate <= 1'b1; // disallow sp to change
addx_mux <= 2'b10; // select sp as addx source
sram_cs_l <= 1'b0; // select sram
code_rd_l_gate <= 1'b0; // and read
w_ophi_gate <= 1'b1;
w_oplo_gate <= 1'b0; // and latch it into reg_oplo
pc_mux <= 1'b0;
w_pc_gate <= 1'b0; // PC = d_bus
w_flag_gate <= 1'b0; // restore flag
next_state <= state_s0;
end
// CALL, part I. Allow the PC to be incremented so, that
// the PC that is pushed onto the stack is pointing to
// the instruction after the call
// what CALL does:
// [SP] <- PC low byte
// SP=SP-1
// [SP] <- PC high 4 bits
// SP=SP-1
else if (reg_opl[7:0]==8'b11010110) begin
w_pc_gate <= 1'b0;
w_ophi_gate <= 1'b0; // latch-in high byte operand
w_oplo_gate <= 1'b1; // deassert oplo gate
next_state <= state_s4;
end
// Must be direct addresing instruction
else begin
next_state <= state_s4;
w_ophi_gate <= 1'b0; // latch-in high byte operand
w_oplo_gate <= 1'b1; // deassert oplo gate
w_pc_gate <= 1'b1; // deassert PC gate.
end
end
/*
** DIRECT INSTRUCTIONS, 3 byte, 5 cycles
*/
state_s4: begin
begin
code_cs_l <= 1'b1;
w_ophi_gate <= 1'b1; // latch-in high byte operand
end
// LMD and STM instructions
if ((reg_opl[7:4]==5'b0110)&&(reg_opl[2:0]!=3'b111)) begin
sram_cs_l <= 1'b0; // select the sram
addx_mux <= 2'b00; // select the sram address
w_pc_gate <= 1'b0; // increment pc on s0
pc_mux <= 1'b1;
alu_func <= 4'b1000; // else c_bus = b_bus
bbus_mux <= 3'b110; // select d_bus by default
// if it is STM
if (reg_opl[3]==1'b1) begin
// while in STM, select c_bus=a_bus only if it's STM acc,xx
if (reg_opl[2:0]==3'b000) begin
alu_func <= 4'b1001; // if DDD=acc c_bus=acc
end
bbus_mux <= reg_opl[2:0]; // select the approp reg
code_wr_l_gate <= 1'b0;
data_bus_wr <= 1'b0; // drive data bus with c_bus
end
// if it is LDM
else begin
code_rd_l_gate <= 1'b0;
w_oplo_gate <= 1'b0; // latchin oplo with sram data on s4
code_rd_l_gate <= 1'b1;
case (reg_opl[2:0]) // latch approp dest reg on s0
3'b001: w_ax_gate <= 1'b0;
3'b010: w_bx_gate <= 1'b0;
3'b101: w_p_gate <= 1'b0;
3'b100: begin
w_flag_gate <= 1'b0;
flag_mux <= 1'b0;
end
default: w_acc_gate <= 1'b0; // else, must be acc
endcase
end
next_state <= state_s0;
end // LMD if
// CALL, 3 bytes, 6 cycles
else if (reg_opl[7:0]==8'b11010110) begin
code_rd_l_gate <= 1'b1;
alu_func <= 4'b1000; // select c_bus=b_bus
bbus_mux <= 3'b011; // select reg_pc low
sp_mux <= 1'b1; // sp = sp - 1 on s5
w_sp_gate <= 1'b0; // allow sp to decrement
addx_mux <= 2'b10; // select sp as addx source
sram_cs_l <= 1'b0; // select sram
code_wr_l_gate <= 1'b0; // and write
data_bus_wr <= 1'b0; // drive data bus with c_bus
w_pc_gate <= 1'b1; //
next_state <= state_s5;
end // call
end // state_s4
/*
** CALL, 3 byte, 6 cycles
** save to [SP], [SP-1] PC+1 not PC
*/
state_s5: begin
if (reg_opl[7:0]==8'b11010110) begin
alu_func <= 4'b1000; // select c_bus=b_bus
bbus_mux <= 3'b100; // select reg_pc hi
sp_mux <= 1'b1; // sp = sp - 1 on s0
w_sp_gate <= 1'b0; // allow sp to decrement
addx_mux <= 2'b10; // select sp as addx source
sram_cs_l <= 1'b0; // select sram
code_wr_l_gate <= 1'b0; // and write
data_bus_wr <= 1'b0; // drive data bus with c_bus
pc_mux <= 1'b0; // PC = d_bus
w_pc_gate <= 1'b0; // allow pc to be changed
next_state <= state_s0;
end
end // state_s5
endcase //state machine
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -