Projects/MCL51/Core/biu.v

426 lines
14 KiB
Verilog

//
//
// File Name : biu.v
// Used on :
// Author : Ted Fried, MicroCore Labs
// Creation : 3/13/16
// Code Type : Synthesizable
//
// Description:
// ============
//
// Bus Interface Unit of the MCL51 processor
// ported to the Lattice XO2 Breakout Board.
//
//------------------------------------------------------------------------
//
// Modification History:
// =====================
//
// Revision 1.0 3/13/16
// Initial revision
//
//
//------------------------------------------------------------------------
//
// Copyright (c) 2020 Ted Fried
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
//------------------------------------------------------------------------
module biu
(
input CORE_CLK, // Core Signals
input RST_n,
input UART_RX, // Peripheral IOs
output UART_TX,
output SPEAKER,
input [7:0] EU_BIU_STROBE, // EU to BIU Signals
input [7:0] EU_BIU_DATAOUT,
input [15:0] EU_REGISTER_R3,
input [15:0] EU_REGISTER_IP,
output [7:0] BIU_SFR_ACC, // BIU to EU Signals
output [15:0] BIU_SFR_DPTR,
output [7:0] BIU_SFR_SP,
output [7:0] BIU_SFR_PSW,
output [7:0] BIU_RETURN_DATA,
output BIU_INTERRUPT,
output RESET_OUT
);
//------------------------------------------------------------------------
// Internal Signals
reg biu_pxy_rd;
reg biu_pxy_wr;
reg core_interrupt_disable;
wire biu_int2;
wire biu_int3;
wire biu_sfr_select;
wire acc_parity;
wire biu_timer_wr_strobe;
wire biu_uart_rd_strobe;
wire biu_uart_wr_strobe;
wire loader_wr;
reg [15:0] eu_register_r3_d1;
reg [7:0] biu_sfr_dpl_int;
reg [7:0] biu_sfr_dph_int;
reg [7:0] biu_sfr_ie_int;
reg [7:0] biu_sfr_psw_int;
reg [7:0] biu_sfr_acc_int;
reg [7:0] biu_sfr_sp_int;
reg [7:0] biu_sfr_b_int;
reg [7:0] biu_sfr_pxy_addr;
reg [7:0] biu_sfr_pxy_dout;
wire [7:0] biu_sfr_pxy_din;
wire [7:0] biu_sfr_dataout;
wire [7:0] biu_sfr_is_int;
wire [7:0] biu_program_data;
wire [2:0] eu_biu_strobe_mode;
wire [2:0] eu_biu_strobe_int;
wire [7:0] biu_ram_dataout;
wire [7:0] biu_timer_dataout;
wire [7:0] biu_uart_dataout;
wire [15:0] loader_addr_int;
wire [7:0] loader_data_int;
//------------------------------------------------------------------------
//
// User Program ROM. 4Kx8
//
//------------------------------------------------------------------------
/* Program ROM without interface to the UART Loader
biu_rom BIU_4Kx8
(
.Reset (1'b0),
.OutClockEn (1'b1),
.OutClock (CORE_CLK),
.Address (EU_REGISTER_IP[11:0]),
.Q (biu_program_data)
);
*/
// For Lattice XO2 Series FPGAs
biu_rom_dp BIU_4Kx8
(
.ResetA (1'b0),
.ClockEnA (1'b1),
.ClockA (CORE_CLK),
.WrA (1'b0),
.AddressA (EU_REGISTER_IP[11:0]),
.DataInA (8'h00),
.QA (biu_program_data),
.ResetB (1'b0),
.ClockEnB (1'b1),
.ClockB (CORE_CLK),
.WrB (loader_wr),
.AddressB (loader_addr_int[11:0]),
.DataInB (loader_data_int),
.QB ( )
);
//------------------------------------------------------------------------
//
// User Data RAM. 512x8
//
//------------------------------------------------------------------------
// For Lattice XO2 Series FPGAs
biu_ram BIU_512x8
(
.Reset (1'b0),
.ClockEn (1'b1),
.Clock (CORE_CLK),
.Address (eu_register_r3_d1[8:0]),
.Data (EU_BIU_DATAOUT),
.Q (biu_ram_dataout),
.WE (biu_ram_wr)
);
//------------------------------------------------------------------------
//
// BIU Combinationals
//
//------------------------------------------------------------------------
// Outputs to the EU
//
assign BIU_SFR_ACC = biu_sfr_acc_int;
assign BIU_SFR_DPTR = { biu_sfr_dph_int , biu_sfr_dpl_int };
assign BIU_SFR_SP = biu_sfr_sp_int;
assign BIU_SFR_PSW = { biu_sfr_psw_int[7:1] , acc_parity };
assign BIU_RETURN_DATA = (eu_biu_strobe_mode==2'h0) ? biu_program_data :
(biu_sfr_select==1'b1) ? biu_sfr_dataout :
biu_ram_dataout ;
// Parity for the Accumulator
// This can be removed if parity is not used in firmware.
assign acc_parity = (biu_sfr_acc_int[0]^biu_sfr_acc_int[1]^biu_sfr_acc_int[2]^biu_sfr_acc_int[3]^biu_sfr_acc_int[4]^biu_sfr_acc_int[5]^biu_sfr_acc_int[6]^biu_sfr_acc_int[7]);
// EU strobes to request BIU processing.
assign eu_biu_strobe_mode[2:0] = EU_BIU_STROBE[6:4];
assign eu_biu_strobe_int[2:0] = EU_BIU_STROBE[2:0];
// Select the SFR range if the address is 0x0080 to 0x00FF and addressing mode is Direct
assign biu_sfr_select = ( eu_register_r3_d1[15:7]==9'b0000_0000_1 && eu_biu_strobe_mode[1:0]==3'h1) ? 1'b1 : 1'b0;
// Decode the write enable to the RAM block
assign biu_ram_wr = (biu_sfr_select==1'b0 && eu_biu_strobe_int==3'h1) ? 1'b1 : 1'b0;
// Mux the SFR data outputs
assign biu_sfr_dataout = (eu_register_r3_d1[7:0]==8'h81) ? biu_sfr_sp_int :
(eu_register_r3_d1[7:0]==8'h82) ? biu_sfr_dpl_int :
(eu_register_r3_d1[7:0]==8'h83) ? biu_sfr_dph_int :
(eu_register_r3_d1[7:0]==8'hA8) ? biu_sfr_ie_int :
(eu_register_r3_d1[7:0]==8'hA9) ? biu_sfr_is_int :
(eu_register_r3_d1[7:0]==8'hC0) ? biu_sfr_pxy_din :
(eu_register_r3_d1[7:0]==8'hD0) ? biu_sfr_psw_int :
(eu_register_r3_d1[7:0]==8'hE0) ? biu_sfr_acc_int :
(eu_register_r3_d1[7:0]==8'hF0) ? biu_sfr_b_int :
8'hEE ;
// Simple fixed priority interrupt controller
// biu_sfr_ie_int[7] is the global_intr_enable
// biu_sfr_is_int[3:0] contains the interrupt source
// Interrupt 2 = Timer Interrupt Vector at address 0x4
// 3 = UART-RX Interrupt Vector at address 0x6
//
assign BIU_INTERRUPT = (core_interrupt_disable==1'b0 && biu_sfr_ie_int[7]==1'b1 && biu_int2==1'b1) ? 1'b1 :
(core_interrupt_disable==1'b0 && biu_sfr_ie_int[7]==1'b1 && biu_int3==1'b1) ? 1'b1 : 1'b0;
// (core_interrupt_disable==1'b0 && biu_sfr_ie_int[7]==1'b1 && biu_int4==1'b1) ? 1'b1 :
// 1'b0 ;
assign biu_sfr_is_int[7:4] = 4'h0;
assign biu_sfr_is_int[3:0] = (biu_int2==1'b1) ? 4'h2 :
(biu_int3==1'b1) ? 4'h3 : 4'hF;
// 4'h4 ;
//------------------------------------------------------------------------
//
// BIU Controller
//
//------------------------------------------------------------------------
//
always @(posedge CORE_CLK)
begin : BIU_CONTROLLER
if (RST_n==1'b0)
begin
biu_sfr_dpl_int <= 'h0;
biu_sfr_dph_int <= 'h0;
biu_sfr_ie_int <= 'h0;
biu_sfr_psw_int <= 'h0;
biu_sfr_acc_int <= 'h0;
biu_sfr_b_int <= 8'h00;
biu_sfr_sp_int <= 'h07;
eu_register_r3_d1 <= 'h0;
biu_pxy_rd <= 'h0;
biu_pxy_wr <= 'h0;
biu_sfr_pxy_addr <= 'h0;
biu_sfr_pxy_dout <= 'h0;
core_interrupt_disable <= 'h0;
end
else
begin
eu_register_r3_d1 <= EU_REGISTER_R3;
if (eu_biu_strobe_int==3'h3)
begin
core_interrupt_disable <= 1'b1;
end
if (eu_biu_strobe_int==3'h4)
begin
core_interrupt_disable <= 1'b0;
end
// Writes to SFR's
if (biu_sfr_select==1'b1 && eu_biu_strobe_int==3'h1)
begin
case (eu_register_r3_d1[7:0]) // synthesis parallel_case
8'h81 : biu_sfr_sp_int <= EU_BIU_DATAOUT[7:0];
8'h82 : biu_sfr_dpl_int <= EU_BIU_DATAOUT[7:0];
8'h83 : biu_sfr_dph_int <= EU_BIU_DATAOUT[7:0];
8'hA8 : biu_sfr_ie_int <= EU_BIU_DATAOUT[7:0];
8'hD0 : biu_sfr_psw_int <= EU_BIU_DATAOUT[7:0];
8'hE0 : biu_sfr_acc_int <= EU_BIU_DATAOUT[7:0];
8'hF0 : biu_sfr_b_int <= EU_BIU_DATAOUT[7:0];
// Proxy Addressing Registers
8'hC1 : biu_sfr_pxy_dout <= EU_BIU_DATAOUT[7:0];
8'hC2 : biu_sfr_pxy_addr <= EU_BIU_DATAOUT[7:0];
default : ;
endcase
end
// Assert the write strobe to the proxy addressed peripherals
if (biu_sfr_select==1'b1 && eu_biu_strobe_int==3'h1 && eu_register_r3_d1[7:0]==8'hC1)
begin
biu_pxy_wr <= 1'b1;
end
else
begin
biu_pxy_wr <= 1'b0;
end
// Assert the read strobe to the proxy addressed peripherals
if (biu_sfr_select==1'b1 && eu_biu_strobe_int==3'h1 && eu_register_r3_d1[7:0]==8'hC2)
begin
biu_pxy_rd <= 1'b1;
end
else
begin
biu_pxy_rd <= 1'b0;
end
end
end
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//
// Peripherals accessed with proxy addressing
//
// BIU SFR biu_sfr_pxy_addr - 0xC2 = Address[7:0]
// biu_sfr_pxy_dout - 0xC1 = Write Data and strobe to the peripherals
// biu_sfr_pxy_din - 0xC0 = Read Data from the peripherals
//
//
//
//------------------------------------------------------------------------
//
// Steer the peripheral read data
assign biu_sfr_pxy_din = (biu_sfr_pxy_addr[7:4]==4'h0) ? biu_timer_dataout :
(biu_sfr_pxy_addr[7:4]==4'h1) ? biu_uart_dataout :
8'hEE ;
// Gate the peripheral read and write strobes
assign biu_timer_wr_strobe = (biu_sfr_pxy_addr[7:4]==4'h0) ? biu_pxy_wr : 1'b0;
assign biu_uart_wr_strobe = (biu_sfr_pxy_addr[7:4]==4'h1) ? biu_pxy_wr : 1'b0;
assign biu_uart_rd_strobe = (biu_sfr_pxy_addr[7:4]==4'h1) ? biu_pxy_rd : 1'b0;
//------------------------------------------------------------------------
//
// Timer - Dual output 24-bit programmable timer
//
// Timer-0 = Frequency generator
// Timer-1 = Pulse generator
//
//------------------------------------------------------------------------
timer BIU_TIMER
(
.CORE_CLK (CORE_CLK),
.RST_n (RST_n),
.ADDRESS (biu_sfr_pxy_addr[3:0]),
.DATA_IN (biu_sfr_pxy_dout),
.DATA_OUT (biu_timer_dataout),
.STROBE_WR (biu_timer_wr_strobe),
.TIMER0_OUT (SPEAKER),
.TIMER1_OUT (biu_int2)
);
//------------------------------------------------------------------------
//
// UART - Fixed 9600 baud
//
//------------------------------------------------------------------------
uart_and_loader BIU_UART
(
.CLK (CORE_CLK),
.RST_n (RST_n),
.ADDRESS (biu_sfr_pxy_addr[1:0]),
.DATA_IN (biu_sfr_pxy_dout),
.DATA_OUT (biu_uart_dataout),
.STROBE_RD (biu_uart_rd_strobe),
.STROBE_WR (biu_uart_wr_strobe),
.UART_RX (UART_RX),
.UART_TX (UART_TX),
.UART_INT (biu_int3),
.LOADER_ADDR (loader_addr_int ),
.LOADER_DATA (loader_data_int ),
.LOADER_WR (loader_wr ),
.RESET_OUT (RESET_OUT )
);
endmodule // biu.v