📄 buscon.v
字号:
//
// BUSCON.V
//
// Bus Controller for PopCorn V3
// This module interfaces to the bus.
// CS, RD, WR are generated here.
//
`include "inc.h"
`timescale 1 ns / 100 ps
module buscon ( // system
sys_clk,
sys_rst_l,
boot_l,
// to/from memory
data_bus_in,
addx_bus,
ready_h,
code_cs_l,
bus_memH,
sram_cs0_l,
sram_cs1_l,
code_rd_l,
code_wr_l,
data_bus_wrL,
// command/handshake
buscon_startH,
buscon_cmd,
buscon_cmdIN,
buscon_doneH,
reg_opl,
reg_oplo,
reg_ophi,
copy_completedH,
bus_cycle_is_portH,
interrupt_pendingH ,
add2_to_PCH,
// to/from datapath
d_bus,
reg_pc,
reg_ax,
reg_bx,
//debug
reg_sp,
SP_change,
sp_delta
);
// ********************************************
//
// INPUT / OUTPUT DECLARATION
//
// ********************************************
// system
input sys_clk;
input sys_rst_l;
input boot_l;
// to/from memory
input [7:0] data_bus_in;
output [`AW-1:0]addx_bus;
input ready_h;
output code_cs_l;
output bus_memH;
output sram_cs0_l;
output sram_cs1_l;
output code_rd_l;
output code_wr_l;
output data_bus_wrL;
// command/handshake
input buscon_startH;
input [8:0] buscon_cmd;
input [8:0] buscon_cmdIN;
output buscon_doneH;
output [7:0] reg_opl;
output [7:0] reg_oplo;
output [`AW-9:0]reg_ophi;
output copy_completedH;
input bus_cycle_is_portH;
input interrupt_pendingH;
input add2_to_PCH;
// to/from datapath
output [`AW-1:0]reg_pc;
output [`AW-1:0]d_bus;
input [7:0] reg_ax;
input [7:0] reg_bx;
// debug
output [`SW-1:0] reg_sp;
output [`SW-1:0] sp_delta;
output SP_change;
parameter HI = 1'b1;
parameter LO = 1'b0;
parameter X = 1'bx;
parameter WAIT_4_REQ = 2'b00,
ASSERT_RDWR = 2'b01,
WAIT_4_READY = 2'b11;
reg [1:0] buscon_state;
reg cs_l;
reg wr_l;
reg rd_l;
reg data_bus_wrL;
reg buscon_doneH;
reg SP_decH;
reg PC_loadH;
reg PC_incH;
reg [7:0] reg_oplIn;
wire [7:0] reg_opl;
reg [7:0] reg_oplo;
reg [`AW-9:0]reg_ophi;
reg [`AW-1:0]reg_pc;
reg [`SW-1:0]reg_sp;
reg [`AW-1:0]addx_bus;
reg copy_completedH;
reg sram_cs0_l;
reg code_cs_l;
reg bus_wrH;
reg next_wait_state;
reg wait_state;
reg readyIN_h;
reg [1:0] wait_state_cntr;
reg inc_wait_state_cntr;
wire SP_incINH;
wire SP_decINH;
wire PC_incINH;
wire PC_loadINH;
wire PC_incrementH;
wire [2:0] addx_mux;
wire writeopH;
wire [`AW-1:0]d_bus;
wire copy_thresholdH;
wire anyCS_l;
wire LOAD_OPL_H;
wire LOAD_OPLO_H;
wire LOAD_OPHI_H;
wire bus_memH;
reg reg2load_opl;
reg reg2load_oplo;
reg reg2load_ophi;
// ****************************************************************
//
// BUS SIGNAL GENERATION
//
// Generates CS, RD and WR
//
// ****************************************************************
assign code_rd_l = rd_l;
assign code_wr_l = wr_l;
//
// bus_cycle_is_portH is a signal from sequencer (seq.v)
// which asserts high or low ONLY during the DATA READ/WRITE
// bus cycles. That is, it is always asserted low during
// opcode fetch cycle. This signal when high, means that
// data is to be read from port memory, when low to be read from
// main memory space
// SRAM_CS1_L
// Asserts low when Addx[MSB] = 1, and the
// bus cycle is active
assign sram_cs1_l = ( cs_l | ~addx_bus[`AW-1] ) | bus_cycle_is_portH;
//assign sram_cs1_l = ~addx_bus[`AW-1];
assign bus_memH = cs_l | ~bus_cycle_is_portH;
// CODE_CS_L and SRAM_CS0_L
//
// ADDRESS DECODE:
// code_cs_l: asserted on the lower 32Kb of addx space
// when boot_l option is not used
// sram_cs0_lL asserted on the lower 32Kb of addx space
// when boot_l option is used.
// sram_cs1_l: asserted on the upper 32Kb of addx space
//
//
//
always @(boot_l or cs_l or addx_bus or copy_completedH or
bus_wrH or bus_cycle_is_portH)
case ({boot_l,copy_completedH})
// normal mode, when copying from FLASH->SRAM is
// not requested. In this case, sram_cs0_l is not
// used
2'b10,
2'b11: begin
code_cs_l = (addx_bus[`AW-1] | bus_cycle_is_portH) | cs_l;
sram_cs0_l = 1'b1;
end
// DURING COPYING
2'b00: begin
code_cs_l = bus_wrH | cs_l;
sram_cs0_l = ~bus_wrH | cs_l;
end
// AFTER COPYING IS DONE
2'b01: begin
code_cs_l = 1'b1;
sram_cs0_l = addx_bus[`AW-1] | bus_cycle_is_portH | cs_l;
end
default: begin
code_cs_l = 1'bx;
sram_cs0_l = 1'bx;
end
endcase
// ********************************************
//
// BUSCONTROLLER (BUSCON)
// SEQUENCING COMMAND
// Decode the command in to control sequences
//
// ********************************************
//
//
// CMD[9:7] addx => {OPLHI,OPLO}=0 PC=1 SP=2 INT_VEC_LO=3 INT_VEC_HI=4 MEM_COPY=5
// CMD[1:0] reg2load => none=0 load_ophiH=1 load_oploH=2 load_oplH=3
//
// 9:7 6 5 4 3 2 1:0
// addx pc_preInc pc_load pc_inc sp_dec sp_inc reg2load
//
//
always @(buscon_cmd)
begin
reg2load_ophi = 1'b0;
reg2load_oplo = 1'b0;
reg2load_opl = 1'b0;
case (buscon_cmd[1:0])
2'b01: reg2load_ophi = 1'b1;
2'b10: reg2load_oplo = 1'b1;
2'b11: reg2load_opl = 1'b1;
default: ;
endcase
end
// LOAD OPERAND HI register
// The current bus cycle will read a byte from the
// address bus and place it to reg_ophi
assign LOAD_OPHI_H = reg2load_ophi;
// LOAD OPERAND LOW register
// The current bus cycle will read a byte from the
// address bus and place it to reg_oplo
assign LOAD_OPLO_H = reg2load_oplo;
// LOAD OPCODE LATCH REGISTER
// The current bus cycle will read a byte from the
// address bus and place it to reg_oplo
assign LOAD_OPL_H = reg2load_opl;
// Pre-Increment SP.
// The incrementing of the stack needs to take place
// at the same time as CS and RD/WR is assrted.
// the only way to do this is to assert SP_incINH
// at the same cycle as buscon_startH. By protocol,
// buscon_startH will be asserted only for 1 tick.
assign SP_incINH = buscon_cmdIN[2] & buscon_startH;
// Post-Decrement SP
// The SP will be decremented by 1 at the completion
// of the current bus cycle
assign SP_decINH = buscon_cmd[3];
// Post-Increment PC. The PC is incremented by 1
// after the bus cycles is completed.
assign PC_incINH = buscon_cmd[4];
// Post-Load PC.
// The PC is loaded with the data presented at the
// d_bus at the completion of the current bus
// cycle
assign PC_loadINH = buscon_cmd[5];
// This steers the address bus with the correct
// source of address:
// 000 d_bus
// 001 reg_pc
// 010 reg_sp
// 011 16'h0010 the low addx of interrupt vector
// 100 16'h0011 the high addx of interrupt vector
//
// This is a cheap way to generate a "latch" equivalant.
// addx_mux will be stable as soon as buscon_cmdIN becomes
// stable.
assign addx_mux = buscon_cmd[8:6];
// when neither opl, oplo nor ophi are request to
// be loaded, this means that we're doing a write
// We use the buscon_cmdIN instead of buscon_cmd
// because it is available 1 tick ahead.
assign writeopH = ~|buscon_cmdIN[1:0];
// bus_wr is stable over the current bus
// transfer and r emains so until the next
// bus transfer. It indcates whether the
// bus cycles is write or read.
always @(posedge sys_clk or negedge sys_rst_l)
if (~sys_rst_l)
bus_wrH <= 1'b0;
else if (buscon_startH)
bus_wrH <= writeopH;
//
// S T A T E M A C H I N E
//
always @(posedge sys_clk or negedge sys_rst_l)
if (~sys_rst_l) begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -