1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-01-28 12:38:43 +00:00
Files
mist-devel.mist-board/tutorials/soc/lesson4/soc.v
2015-11-26 13:52:16 +01:00

143 lines
3.9 KiB
Verilog

// A simple system-on-a-chip (SoC) for the MiST
// (c) 2015 Till Harbaum
module soc (
input [1:0] CLOCK_27,
// SDRAM interface
inout [15:0] SDRAM_DQ, // SDRAM Data bus 16 Bits
output [12:0] SDRAM_A, // SDRAM Address bus 13 Bits
output SDRAM_DQML, // SDRAM Low-byte Data Mask
output SDRAM_DQMH, // SDRAM High-byte Data Mask
output SDRAM_nWE, // SDRAM Write Enable
output SDRAM_nCAS, // SDRAM Column Address Strobe
output SDRAM_nRAS, // SDRAM Row Address Strobe
output SDRAM_nCS, // SDRAM Chip Select
output [1:0] SDRAM_BA, // SDRAM Bank Address
output SDRAM_CLK, // SDRAM Clock
output SDRAM_CKE, // SDRAM Clock Enable
// VGA interface
output VGA_HS,
output VGA_VS,
output [5:0] VGA_R,
output [5:0] VGA_G,
output [5:0] VGA_B
);
wire pixel_clock;
// include VGA controller
vga vga (
.pclk ( pixel_clock ),
.cpu_clk ( cpu_clock ),
.cpu_wr ( !cpu_wr_n && !cpu_addr[15] ),
.cpu_addr ( cpu_addr[13:0] ),
.cpu_data ( cpu_dout ),
.hs (VGA_HS),
.vs (VGA_VS),
.r (VGA_R),
.g (VGA_G),
.b (VGA_B)
);
// The CPU is kept in reset for further 256 cyckes after the PLL is
// generating stable clocks to make sure things like the SDRAM have
// some time to initialize
reg [7:0] cpu_reset_cnt = 8'h00;
wire cpu_reset = (cpu_reset_cnt != 255);
always @(posedge cpu_clock) begin
if(!pll_locked)
cpu_reset_cnt <= 8'd0;
else
if(cpu_reset_cnt != 255)
cpu_reset_cnt <= cpu_reset_cnt + 8'd1;
end
// SDRAM control signals
wire ram_clock;
assign SDRAM_CKE = 1'b1;
sdram sdram (
// interface to the MT48LC16M16 chip
.sd_data ( SDRAM_DQ ),
.sd_addr ( SDRAM_A ),
.sd_dqm ( {SDRAM_DQMH, SDRAM_DQML} ),
.sd_cs ( SDRAM_nCS ),
.sd_ba ( SDRAM_BA ),
.sd_we ( SDRAM_nWE ),
.sd_ras ( SDRAM_nRAS ),
.sd_cas ( SDRAM_nCAS ),
// system interface
.clk ( ram_clock ),
.clkref ( cpu_clock ),
.init ( !pll_locked ),
// cpu/chipset interface
.din ( cpu_dout ),
.addr ( { 10'd0, cpu_addr[14:0] } ),
.we ( !cpu_wr_n && cpu_addr[15] ),
.oe ( !cpu_rd_n && cpu_addr[15] ),
.dout ( ram_data_out )
);
// CPU control signals
wire cpu_clock;
wire [15:0] cpu_addr;
wire [7:0] cpu_din;
wire [7:0] cpu_dout;
wire cpu_rd_n;
wire cpu_wr_n;
wire cpu_mreq_n;
// include Z80 CPU
T80s T80s (
.RESET_n ( !cpu_reset ),
.CLK_n ( cpu_clock ),
.WAIT_n ( 1'b1 ),
.INT_n ( 1'b1 ),
.NMI_n ( 1'b1 ),
.BUSRQ_n ( 1'b1 ),
.MREQ_n ( cpu_mreq_n ),
.RD_n ( cpu_rd_n ),
.WR_n ( cpu_wr_n ),
.A ( cpu_addr ),
.DI ( cpu_din ),
.DO ( cpu_dout )
);
// map 32k SDRAM into upper half od the address space (A15=1)
// and 4k ROM into the lower half (A15=0)
wire [7:0] ram_data_out, rom_data_out;
assign cpu_din = cpu_addr[15]?ram_data_out:rom_data_out;
// include 4k program code from boot_rom
boot_rom boot_rom (
.clock ( cpu_clock ),
.address ( cpu_addr[11:0] ),
.q ( rom_data_out )
);
// derive 4Mhz cpu clock from 32Mhz sdram clock
assign cpu_clock = clk_div[2];
reg [2:0] clk_div;
always @(posedge ram_clock)
clk_div <= clk_div + 3'd1;
// PLL to generate 32Mhz ram clock and 25Mhz video clock from MiSTs
// 27Mhz on board clock
wire pll_locked;
pll pll (
.inclk0 ( CLOCK_27[0] ),
.locked ( pll_locked ), // PLL is running stable
.c0 ( pixel_clock ), // 25.175 MHz
.c1 ( ram_clock ), // 32 MHz
.c2 ( SDRAM_CLK ) // slightly phase shifted 32 MHz
);
endmodule