📄 sequencer.v
字号:
/*
** SEQUENCER
**
** This core adheres to GNU Public Licence
** Jeung Joon Lee *** www.cmosexod.com
** joon.lee@quantum.com
**
** JJL 12/12/98
** updated 3/16/2000
**
**
** This is the sequencer for the POPCORN 8bit microprocessor.
** Controls all of the control signals.
**
** This sequencer controls these following signals of the datapath "popcorn"
**
**
**
*/
module sequencer (sys_clk,
phase_1_clk,
sys_rst,
w_acc,
w_ax,
w_bx,
w_p,
w_flag,
bbus_mux,
alu_func,
pc_mux,
addx_mux,
sp_mux,
flag_mux,
w_sp,
w_pc,
w_oplo,
w_ophi,
w_opl,
reg_opl,
code_cs_l,
code_rd_l,
sram_cs_l,
code_wr_l,
reg_flag,
data_bus_wr,
next_state
);
input sys_clk,sys_rst,phase_1_clk;
input [7:0] reg_opl;
input [2:0] reg_flag;
output w_acc,w_ax,w_bx,w_p,w_flag,pc_mux,w_pc;
output w_opl,w_oplo,w_ophi,code_cs_l,code_rd_l;
output [3:0] alu_func;
output [2:0] bbus_mux;
output [3:0] next_state;
output [1:0] addx_mux;
output sp_mux, w_sp, sram_cs_l, code_wr_l, data_bus_wr;
output flag_mux;
reg [5:0] next_state;
reg code_cs_l,code_rd_l_gate;
reg w_opl_gate,w_acc_gate,w_ax_gate,w_bx_gate;
reg w_p_gate,w_flag_gate,pc_mux;
reg w_oplo_gate,w_ophi_gate,w_pc_gate;
reg [3:0] alu_func;
reg [2:0] bbus_mux;
reg dummy;
reg [1:0] addx_mux;
reg w_sp_gate, sp_mux, sram_cs_l, code_wr_l_gate,data_bus_wr;
reg flag_mux;
parameter state_s0 =6'b000001;
parameter state_s1 =6'b000010;
parameter state_s2 =6'b000100;
parameter state_s3 =6'b001000;
parameter state_s4 =6'b010000;
parameter state_s5 =6'b100000;
assign w_acc = w_acc_gate;
assign w_ax = w_ax_gate;
assign w_bx = w_bx_gate;
assign w_p = w_p_gate;
assign w_flag= w_flag_gate;
assign w_pc = w_pc_gate;
assign w_sp = w_sp_gate;
assign w_oplo= w_oplo_gate | phase_1_clk; // asynchronous reg
assign w_ophi= w_ophi_gate | phase_1_clk; // asynchronous reg
assign w_opl = w_opl_gate | phase_1_clk; // asynchronous reg
assign code_rd_l = code_rd_l_gate | phase_1_clk; // code rom rd
assign code_wr_l = code_wr_l_gate | phase_1_clk;
/*
** Behavioral description of the Sequencer State machine
**
** synchronous state machine, transitions on the rising edge of sys_clk
*/
always @(posedge sys_clk or negedge sys_rst) begin
if (~sys_rst) begin // rst
code_cs_l <= 1'b1;
code_rd_l_gate <= 1'b1;
code_wr_l_gate <= 1'b1;
sram_cs_l <= 1'b1;
alu_func <= 4'b0000;
w_acc_gate <= 1'b1;
w_ax_gate <= 1'b1;
w_bx_gate <= 1'b1;
w_p_gate <= 1'b1;
w_flag_gate <= 1'b1;
w_opl_gate <= 1'b1;
w_oplo_gate <= 1'b1;
w_ophi_gate <= 1'b1;
bbus_mux <= 2'b00;
addx_mux <= 2'b01;
pc_mux <= 1'b1;
sp_mux <= 1'b1;
flag_mux <= 1'b1;
w_pc_gate <= 1'b1;
w_sp_gate <= 1'b1;
data_bus_wr <= 1'b1;
// port_bus_ena <= 1'b0;
next_state <= state_s0;
end
else case(next_state)
/*
** FETCH OPCODE STATE. (at beginning of s1 opcode is latched into reg_opl)
*/
state_s0: begin // *****2
code_cs_l <= 1'b0; // enable code cs
code_rd_l_gate <= 1'b0; // enable code rd
code_wr_l_gate <= 1'b1;
sram_cs_l <= 1'b1;
alu_func <= 4'bx;
w_acc_gate <= 1'b1;
w_ax_gate <= 1'b1;
w_bx_gate <= 1'b1;
w_p_gate <= 1'b1;
w_flag_gate <= 1'b1;
w_opl_gate <= 1'b0; // latch opl at s1
w_oplo_gate <= 1'b1;
w_ophi_gate <= 1'b1;
bbus_mux <= 2'b00;
addx_mux <= 2'b01;
pc_mux <= 1'b1;
sp_mux <= 1'b1;
flag_mux <= 1'b1;
w_pc_gate <= 1'b1;
w_sp_gate <= 1'b1;
data_bus_wr <= 1'b1;
//port_bus_ena <= 1'b0;
next_state <= state_s1;
end
/*
** REGISTER DIRECT INSTRUCTIONS 1 byte, 2 cycle instructions
** these are: stacc, ldacc, and alu ops
*/
state_s1: begin // ******** 2
begin
code_cs_l <= 1'b1; // disable cs and rd from code ram
code_rd_l_gate <= 1'b1;
w_opl_gate <= 1'b1; // disable opcode latch gate
end
// ALU opcode - register direct
if((reg_opl[7:6]==2'b00)&&(reg_opl[2:0]!=3'b111)) begin
alu_func <= reg_opl[6:3];
w_acc_gate <= 1'b0; // latch acc with result on s0
w_flag_gate <= 1'b0; // latch reg result on s0
bbus_mux <= reg_opl[2:0];
w_pc_gate <= 1'b0; // increment pc on s0
next_state <= state_s0;
end
// CMPACC opcode - register direct
else if((reg_opl[7:3]==5'b01000)&&(reg_opl[2:0]!=3'b111)) begin
alu_func <= 4'b0001; // alu subtract
w_flag_gate <= 1'b0; // latch reg result on s0
bbus_mux <= reg_opl[2:0];
w_pc_gate <= 1'b0; // increment pc on s0
next_state <= state_s0;
end
// LDACC - register direct
else if ((reg_opl[7:3]==5'b10001)&&(reg_opl[2:0]!=3'b111)) begin
alu_func <= 4'b1000; // alu=select b bus
w_acc_gate <= 1'b0; // latch acc on s0
bbus_mux <= reg_opl[2:0];
w_pc_gate <= 1'b0; // increment pc on s0
next_state <= state_s0;
end
// STACC - register direct
else if ((reg_opl[7:3]==5'b10010)&&(reg_opl[2:0]!=3'b111)) begin
alu_func <= 4'b1001; // alu=select a bus
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'b100: begin
w_flag_gate <= 1'b0;
flag_mux <= 1'b0;
end
3'b101: w_p_gate <= 1'b0;
default: dummy <= 1'b0; // do nothing
endcase
bbus_mux <= 3'b001; // anything but 3'b101 (port)
w_pc_gate <= 1'b0; // increment pc in s0
next_state <= state_s0;
end
// PUSH , write out to [SP] and decrement SP
// push does this: [SP] <- reg, SP=SP-1
else if(reg_opl[7:3]==5'b01110) begin
if (reg_opl[2:0]==3'b000) begin
alu_func <= 4'b1001; // select c_bus=acc
end else begin
alu_func <= 4'b1000; // select c_bus=b_bus
end
bbus_mux <= reg_opl[2:0];
sp_mux <= 1'b1; // sp = sp -1
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'b0; // increment pc on s0
next_state <= state_s0;
end
// POP, RET part I, increment SP
// pop does this:
// SP=SP+1
// reg_ophi <- [SP]
// SP=SP+1
// reg_oplo <- [SP]
else if (reg_opl[7:3]==5'b01111 | reg_opl[7:0]==8'b11011110) begin
alu_func <= 4'b1000; // c_bus = b_bus
bbus_mux <= 3'b110; // b_bus = d_bus
sp_mux <= 1'b0; // sp = sp + 1
w_sp_gate <= 1'b0; // allow sp to increment
next_state <= state_s2;
end
// Immediate mode, so need to go and fetch one or two operands.
// setup the PC so it increments to 1 and cs and rd gates
// are asserted
else begin
alu_func <= 4'b1000;
w_acc_gate <= 1'b1;
w_ax_gate <= 1'b1;
w_bx_gate <= 1'b1;
w_p_gate <= 1'b1;
w_oplo_gate <= 1'b1;
bbus_mux <= 3'b110; // show d_bus on c_bus
pc_mux <= 1'b1;
w_pc_gate <= 1'b0; // increment pc on s2
next_state <= state_s2;
end
end
/*
** IMMEDIATE INSTRUCTIONS. 2 bytes, 3 cycle insruction
** these are: ldi, alu ops.
*/
state_s2: begin
// LDI - load immediate 8 bit value to register
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -