git-svn-id: http://moon:8086/svn/vhdl/trunk@1425 cc03376c-175c-47c8-b038-4cd826a8556b
336 lines
9.2 KiB
Verilog
336 lines
9.2 KiB
Verilog
/* PC.V
|
|
**
|
|
** 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
|
|
**
|
|
** Highest module for the 8 bit general purpose microprocessor
|
|
** Two submodules are declerared here, popcorn.v and sequencer.v
|
|
** The role and functions of these modules are as following:
|
|
** PC.V wrapper, and clock generator. Provides to the submodules
|
|
** sys_clk and phase_1_clk
|
|
** POPCORN.V The 8 bit datapath. Contains the ALU, register file,
|
|
** the program counter, stack pointer and all of the muxes.
|
|
** SEQUENCER.V The sequencer state machine. BAsed on the fetched opcode,
|
|
** generates all of the sequence of control signals to
|
|
** fetch more operands or finish executing the opcode.
|
|
**
|
|
*/
|
|
|
|
`include "inc.h"
|
|
|
|
module pc( sys_clk,
|
|
sys_rst,
|
|
addx_bus,
|
|
data_bus,
|
|
code_cs_l,
|
|
code_rd_l,
|
|
code_wr_l,
|
|
sram_cs_l,
|
|
slow_clk,
|
|
port
|
|
|
|
`ifdef show_debug_pins
|
|
,
|
|
w_opl,
|
|
w_pc,
|
|
w_oplo,
|
|
state,
|
|
w_acc,
|
|
w_ax,
|
|
w_bx,
|
|
w_p,
|
|
w_ophi,
|
|
w_flag,
|
|
phase_1_clk,
|
|
slow_clk4,
|
|
reg_flag,
|
|
tst_bus,
|
|
reg_acc,
|
|
reg_ax,
|
|
reg_bx,
|
|
reg_p,
|
|
reg_opl
|
|
`endif
|
|
|
|
);
|
|
|
|
|
|
parameter N=6;
|
|
|
|
|
|
input sys_clk;
|
|
input sys_rst;
|
|
inout [7:0] data_bus;
|
|
inout [7:0] port;
|
|
//input [1:0] tst_bus_sel;
|
|
output [11:0] addx_bus;
|
|
//output [7:0] tst_bus;
|
|
output code_cs_l, code_rd_l, code_wr_l, sram_cs_l;
|
|
output slow_clk;
|
|
|
|
`ifdef show_debug_pins
|
|
// DEBUG SIGNALS
|
|
output w_opl;
|
|
output w_pc;
|
|
output w_oplo;
|
|
output [3:0] state;
|
|
output w_acc;
|
|
output w_ax;
|
|
output w_bx;
|
|
output w_p;
|
|
output w_ophi;
|
|
output w_flag;
|
|
output phase_1_clk;
|
|
output slow_clk4;
|
|
output [2:0] reg_flag;
|
|
output tst_bus;
|
|
output [7:0] reg_acc;
|
|
output [7:0] reg_ax;
|
|
output [7:0] reg_bx;
|
|
output [7:0] reg_p;
|
|
output [7:0] reg_opl;
|
|
`endif
|
|
|
|
wire w_acc,w_ax,w_bx,w_p,w_flag;
|
|
wire pc_mux,w_pc,w_oplo,w_ophi,w_opl;
|
|
wire slow_clk4;
|
|
wire [2:0] bbus_mux;
|
|
wire [3:0] alu_func;
|
|
wire [2:0] reg_flag;
|
|
wire [7:0] port;
|
|
reg [1:0] state_slow_clk4;
|
|
reg phase_1_clk;
|
|
wire xx,slow_clk;
|
|
wire [5:0] state;
|
|
wire [7:0] b_bus,c_bus;
|
|
wire [11:0] d_bus;
|
|
wire [7:0] tst_bus;
|
|
wire sp_mux, w_sp;
|
|
wire [1:0] addx_mux;
|
|
wire data_bus_wr;
|
|
wire sram_cs_l, code_wr_l;
|
|
wire flag_mux;
|
|
wire [7:0] reg_acc;
|
|
wire [7:0] reg_ax;
|
|
wire [7:0] reg_bx;
|
|
wire [7:0] reg_p;
|
|
wire [7:0] reg_opl;
|
|
//wire [7:0] port_in;
|
|
//wire port_bus_ena;
|
|
|
|
// define test bus
|
|
/*
|
|
always @(tst_bus_sel or reg_opl or c_bus or b_bus or d_bus)
|
|
case (tst_bus_sel)
|
|
2'b00: tst_bus <= reg_opl;
|
|
//2'b01: tst_bus <= b_bus;
|
|
default: tst_bus <= b_bus;
|
|
//2'b10: tst_bus <= c_bus;
|
|
//default: tst_bus <= c_bus;
|
|
//2'b11: tst_bus <= d_bus;
|
|
endcase
|
|
*/
|
|
//assign tst_bus=tst_bus_sel[0] ? b_bus : c_bus;
|
|
assign tst_bus=c_bus;
|
|
|
|
|
|
`ifdef use_clock_divider
|
|
//
|
|
// CLOCK DIVIDER
|
|
//
|
|
//
|
|
// N=5 sets for 1Mhz operation
|
|
// N=7 sets for 250Khz op. good for slow speed debug
|
|
reg [N-1:0] clk;
|
|
always @(posedge sys_clk or negedge sys_rst)
|
|
if (~sys_rst) clk <=0;
|
|
else clk <= clk + 1;
|
|
assign slow_clk = clk[N-1];
|
|
assign slow_clk4 = ~clk[N-3];
|
|
`else
|
|
reg [1:0] clk;
|
|
always @(posedge sys_clk or negedge sys_rst)
|
|
if (~sys_rst) clk <= 2'b00;
|
|
else clk <= clk + 1;
|
|
assign slow_clk = clk[1];
|
|
assign slow_clk4 = sys_clk;
|
|
`endif
|
|
|
|
/* define phase_1 clock
|
|
** | |
|
|
** | ___ ___ ___ ___ | ___ ___
|
|
** slow_clk*4 |/ \___/ \___/ \___/ \___|/ \___/ \___
|
|
** | _______ _______ | _______
|
|
** slow_clk*2 |/ \_______/ \_______|/ \_______
|
|
** | _______________ | _______________
|
|
** slow_clk |/ \_______________|/
|
|
** |________ _______|_
|
|
** phase_1 | \_______________/ |
|
|
** | |
|
|
*/
|
|
always @(posedge slow_clk4 or negedge sys_rst)
|
|
if (~sys_rst) begin
|
|
state_slow_clk4<=2'b00;
|
|
phase_1_clk<=1'b1;
|
|
end
|
|
else case (state_slow_clk4)
|
|
2'b00: begin state_slow_clk4<=2'b01; phase_1_clk<=1'b1; end
|
|
2'b01: begin state_slow_clk4<=2'b11; phase_1_clk<=1'b1; end
|
|
2'b11: begin state_slow_clk4<=2'b10; phase_1_clk<=1'b0; end
|
|
2'b10: begin state_slow_clk4<=2'b00; phase_1_clk<=1'b0; end
|
|
endcase
|
|
|
|
// instantiate the datapath
|
|
popcorn POPCORN( .sys_clk(slow_clk),
|
|
.sys_rst(sys_rst),
|
|
.w_acc(w_acc),
|
|
.w_ax(w_ax),
|
|
.w_bx(w_bx),
|
|
.w_p(w_p),
|
|
.w_flag(w_flag),
|
|
.bbus_mux(bbus_mux),
|
|
.alu_func(alu_func),
|
|
.pc_mux(pc_mux),
|
|
.sp_mux(sp_mux),
|
|
.flag_mux(flag_mux),
|
|
.addx_mux(addx_mux),
|
|
.w_pc(w_pc),
|
|
.w_sp(w_sp),
|
|
.w_oplo(w_oplo),
|
|
.w_ophi(w_ophi),
|
|
.w_opl(w_opl),
|
|
.data_bus(data_bus),
|
|
.port(port),
|
|
// .port_in(port_in),
|
|
.addx_bus(addx_bus),
|
|
.reg_opl(reg_opl),
|
|
.reg_flag(reg_flag),
|
|
.b_bus(b_bus),
|
|
.c_bus(c_bus),
|
|
.d_bus(d_bus),
|
|
.data_bus_wr(data_bus_wr),
|
|
.code_wr_l(code_wr_l),
|
|
.reg_acc(reg_acc),
|
|
.reg_ax(reg_ax),
|
|
.reg_bx(reg_bx),
|
|
.reg_p(reg_p)
|
|
);
|
|
|
|
// instantiate the sequencer
|
|
sequencer SEQ ( .sys_clk(slow_clk),
|
|
.phase_1_clk(phase_1_clk),
|
|
.sys_rst(sys_rst),
|
|
.w_acc(w_acc),
|
|
.w_ax(w_ax),
|
|
.w_bx(w_bx),
|
|
.w_p(w_p),
|
|
.w_flag(w_flag),
|
|
.bbus_mux(bbus_mux),
|
|
.alu_func(alu_func),
|
|
.pc_mux(pc_mux),
|
|
.addx_mux(addx_mux),
|
|
.sp_mux(sp_mux),
|
|
.flag_mux(flag_mux),
|
|
.w_pc(w_pc),
|
|
.w_sp(w_sp),
|
|
.w_oplo(w_oplo),
|
|
.w_ophi(w_ophi),
|
|
.w_opl(w_opl),
|
|
.reg_opl(reg_opl),
|
|
.code_cs_l(code_cs_l),
|
|
.code_rd_l(code_rd_l),
|
|
.code_wr_l(code_wr_l),
|
|
.sram_cs_l(sram_cs_l),
|
|
.reg_flag(reg_flag),
|
|
.data_bus_wr(data_bus_wr),
|
|
.next_state(state)
|
|
);
|
|
|
|
|
|
|
|
endmodule
|
|
|
|
|
|
|
|
/*
|
|
** Note on pin assignment:
|
|
** o use pin file : "finalpin.pin"
|
|
** o use global clock Y0 for 66Mhz source
|
|
** o use global reset for reset.
|
|
** o use N=6. This requires 64Mhz to give internal clock speed of 1Mhz.
|
|
**
|
|
** 2/12/99
|
|
** o Fixed the LDM ACC,xx bug. ALU was not being set for c_bus = b_bus.
|
|
** Call this 'popcorn - final'
|
|
**
|
|
** 2/11/99
|
|
** o Uncovered and fixed 2 bugs relating the IO PORT:
|
|
** 1.The signals 'reg_port_gate' which controls the gate of the port
|
|
** output buffer has the wrong polarity. This was causing the port
|
|
** to drive the port IO pin only when it was being read.
|
|
** 2.The state of the bbus_mux[2:0] during LDACC/STADD was set to unknown.
|
|
** This was causing the reg_port_gate to be deasserted during LDACC PORT
|
|
** or STACC PORT instructions for 1 cycle, causing glitches in the IO port
|
|
** pin
|
|
**
|
|
** 1/8/99
|
|
** o Succesfully ran a timer program which toggles all bits of the
|
|
** port register at 2mS interval (period=4mS). The program uses
|
|
** an instrunctions timed 2mS delay subroutine.
|
|
**
|
|
** 1/7/99
|
|
** o Somewhat final version. The test bus (TST[7:0]) has been dropped
|
|
** and PORT[7:0] been used. All instructions works at least at 2 Mhz.
|
|
** Call this 'popcorn -v5'
|
|
**
|
|
** 1/5/99
|
|
** o Droppped the automatic pushing and popping of the flags when CALL/RET
|
|
** are executed, (could not fit). So reduced the size of REG_OPHI down
|
|
** to 4 from 8 bits. Instead the pushing of the flag is now done with
|
|
** LDACC flag
|
|
** LDM flag, #addx
|
|
** PUSH flag
|
|
** POP flag
|
|
** instructions. The flag register still is muxed from ALU and c_bus.
|
|
** Thanks Lord.
|
|
** All that remains now is implementation of interrupt support.
|
|
**
|
|
** 1/3/99
|
|
** o Removed DX and CX register from the register file, to free-up
|
|
** the b_mux. The freed b_bus mux inputs are used by the PC (hi and low).
|
|
** This allows PC to be pushed into the stack as well as CALL and RET
|
|
** and push flag instructions
|
|
**
|
|
** 1/1/99
|
|
** o Removed 7 level-deep hardware stack - it was obvious that this is not
|
|
** a very robust way of having a stack. It limits the CALL/RET depth.
|
|
** However my initial rational for not implementing the SP was that I
|
|
** did not wanted to have a SRAM for stack. SRAM automatically implies
|
|
** an extenal IC (since on FPGA you could not provide the required
|
|
** amount of space).
|
|
** o Added another addressing mode: direct mode, and 2 instructions: LDM and
|
|
** STM (load mem, store mem). This brings the modes
|
|
** to: register direct, immediate and direct.
|
|
** Why not, I had decided to have exnal SRAM, so let's make use of it
|
|
**
|
|
** 12/28/98
|
|
** o Added 7-level deep hardware LIFO to implement pushacc/popacc
|
|
** instructions
|
|
** o Implemented pushacc and popacc instructions in the sequencer.v
|
|
**
|
|
** 12/27/98
|
|
** o Fixed a number of bugs, including CMPACC (reg direct) and ALU ops (reg
|
|
** direct) being decoded as same.
|
|
**
|
|
** 12/26/98
|
|
** o Shortenend the PC to 12 bits from 16, to reduce design size.
|
|
** o REduced the datapath width to 8 from 16, to reduce design size.
|
|
**
|
|
** Lots of previous history not accounted for. Started to work on POPCORN
|
|
** about 12/12/98
|
|
*/
|