gateware

A collection of little open source FPGA hobby projects
git clone http://frotz.net/git/gateware.git
Log | Files | Refs | README

system_cpu16_vga40x30.v (4273B)


      1 // Copyright 2015, Brian Swetland <swetland@frotz.net>
      2 // Licensed under the Apache License, Version 2.0.
      3 
      4 `default_nettype none
      5 
      6 `timescale 1ns / 1ps
      7 
      8 `define WITH_CPU
      9 
     10 module system_cpu16_vga40x30 #(
     11 	parameter BPP = 2
     12 )(
     13 	input clk12m_in,
     14 	output [BPP-1:0]vga_red,
     15 	output [BPP-1:0]vga_grn,
     16 	output [BPP-1:0]vga_blu,
     17 	output vga_hsync,
     18 	output vga_vsync,
     19 	output vga_active,
     20 	output vga_clk,
     21 	input spi_mosi,
     22 	output spi_miso,
     23 	input spi_clk,
     24 	input spi_cs,
     25 	input uart_rx,
     26 	output uart_tx,
     27 	output led_red,
     28 	output led_grn,
     29 	output out1,
     30 	output out2
     31 );
     32 
     33 wire clk12m;
     34 wire clk25m;
     35 
     36 assign out1 = clk12m;
     37 assign out2 = clk25m;
     38 
     39 pll_12_25 pll0(
     40 	.clk12m_in(clk12m_in),
     41 	.clk12m_out(clk12m),
     42 	.clk25m_out(clk25m),
     43 	.lock(),
     44 	.reset(1'b1)
     45 	);
     46 
     47 wire sys_clk;
     48 
     49 `ifdef USE_HFOSC
     50 SB_HFOSC #(
     51 	.CLKHF_DIV("0b00")
     52 	)hfosc(
     53 	.CLKHFEN(1'b1),
     54 	.CLKHFPU(1'b1),
     55 	.CLKHF(sys_clk)
     56 	);
     57 `else
     58 assign sys_clk = clk12m;
     59 `endif
     60 
     61 reg cpu_reset = 1'b0;
     62 
     63 // cpu memory interface
     64 wire [15:0]ins_rd_addr;
     65 wire [15:0]ins_rd_data;
     66 wire ins_rd_req;
     67 
     68 wire [15:0]dat_rw_addr;
     69 wire [15:0]dat_rd_data;
     70 wire dat_rd_req;
     71 wire [15:0]dat_wr_data;
     72 wire dat_wr_req;
     73 
     74 `ifndef WITH_CPU
     75 assign ins_rd_req = 1'b0;
     76 assign dat_rd_req = 1'b0;
     77 assign dat_wr_req = 1'b0;
     78 assign ins_rd_addr = 16'd0;
     79 assign dat_rw_addr = 16'd0;
     80 `else
     81 // fake arbitration that never denies a request
     82 reg ins_rd_rdy = 1'b0;
     83 reg dat_rd_rdy = 1'b0;
     84 reg dat_wr_rdy = 1'b0;
     85 
     86 always_ff @(posedge sys_clk) begin
     87 	if (cpu_reset) begin
     88 		ins_rd_rdy <= 1'b0;
     89 		dat_rd_rdy <= 1'b0;
     90 		dat_wr_rdy <= 1'b0;
     91 	end else begin
     92 		ins_rd_rdy <= ins_rd_req;
     93 		dat_rd_rdy <= dat_rd_req;
     94 		dat_wr_rdy <= dat_wr_req;
     95 	end
     96 end
     97 
     98 // until arbitration works
     99 assign dat_rd_data = 16'hEEEE;
    100 
    101 cpu16 cpu(
    102 	.clk(sys_clk),
    103 	.ins_rd_addr(ins_rd_addr),
    104 	.ins_rd_data(ins_rd_data),
    105 	.ins_rd_req(ins_rd_req),
    106 	.ins_rd_rdy(ins_rd_rdy),
    107 
    108 	.dat_rw_addr(dat_rw_addr),
    109 	.dat_wr_data(dat_wr_data),
    110 	.dat_rd_data(dat_rd_data),
    111 	.dat_rd_req(dat_rd_req),
    112 	.dat_rd_rdy(dat_rd_rdy),
    113 	.dat_wr_req(dat_wr_req),
    114 	.dat_wr_rdy(dat_wr_rdy),
    115 
    116 	.reset(cpu_reset)
    117 	) /* synthesis syn_keep=1 */;
    118 `endif
    119 
    120 wire [15:0]dbg_waddr;
    121 wire [15:0]dbg_wdata;
    122 wire dbg_we;
    123 
    124 `ifdef WITH_SPI_DEBUG
    125 spi_debug_ifc sdi(
    126 	.spi_clk(spi_clk),
    127 	.spi_cs_i(spi_cs),
    128 	.spi_data_i(spi_mosi),
    129 	.spi_data_o(spi_miso),
    130 	.sys_clk(sys_clk),
    131 	.sys_wr_o(dbg_we),
    132 	.sys_waddr_o(dbg_waddr),
    133 	.sys_wdata_o(dbg_wdata)
    134 	);
    135 `else
    136 uart_debug_ifc uart(
    137 	.sys_clk(sys_clk),
    138 	.sys_wr(dbg_we),
    139 	.sys_waddr(dbg_waddr),
    140 	.sys_wdata(dbg_wdata),
    141 	.uart_rx(uart_rx),
    142 	.uart_tx(uart_tx),
    143 	.led_red(led_red),
    144 	.led_grn(led_grn)
    145 	);
    146 `endif	
    147 
    148 // debug interface has priority over cpu writes
    149 wire we = dbg_we | dat_wr_req;
    150 wire [15:0]waddr = dbg_we ? dbg_waddr : dat_rw_addr;
    151 wire [15:0]wdata = dbg_we ? dbg_wdata : dat_wr_data;
    152 
    153 wire w_cs_sram = (waddr[15:12] == 4'h0);
    154 wire w_cs_vram = (waddr[15:12] == 4'h8);
    155 wire w_cs_ctrl = (waddr[15:12] == 4'hF);
    156 
    157 always @(posedge sys_clk) begin
    158 	if (w_cs_ctrl & we) begin
    159 		cpu_reset <= wdata[0];
    160 	end
    161 end
    162 
    163 sram ram0(
    164 	.clk(sys_clk),
    165 	.raddr(ins_rd_addr),
    166 	.rdata(ins_rd_data),
    167 	.re(ins_rd_req),
    168 	.waddr(waddr),
    169 	.wdata(wdata),
    170 	.we(we & w_cs_sram)
    171 	);
    172 
    173 wire [BPP-1:0]vr;
    174 wire [BPP-1:0]vg;
    175 wire [BPP-1:0]vb;
    176 
    177 vga40x30x2 #(
    178 	.BPP(BPP),
    179 	.RGB(0)
    180 	) vga (
    181 	.clk25m(clk25m),
    182 	.red(vr),
    183 	.grn(vg),
    184 	.blu(vb),
    185 	.hs(vga_hsync),
    186 	.vs(vga_vsync),
    187 	.fr(),
    188 	.active(vga_active),
    189 	.vram_waddr(waddr[10:0]),
    190 	.vram_wdata(wdata[15:0]),
    191 	.vram_we(we & w_cs_vram),
    192 	.vram_clk(sys_clk)
    193 	);
    194 
    195 assign vga_clk = clk25m;
    196 
    197 // hack: flip display from blue to red when CPU is held in reset
    198 assign vga_red = cpu_reset ? vb : vr;
    199 assign vga_grn = vg;
    200 assign vga_blu = cpu_reset ? vr : vb;
    201 
    202 endmodule
    203 
    204 module sram(
    205 	input clk,
    206 	input [15:0]raddr,
    207 	output [15:0]rdata,
    208 	input re,
    209 	input [15:0]waddr,
    210 	input [15:0]wdata,
    211 	input we
    212 	);
    213 
    214 `ifndef USE_LATTICE_SB_RAM40
    215 reg [15:0]mem[255:0];
    216 reg [15:0]ra;
    217 always @(posedge clk) begin
    218 	if (we)
    219 		mem[waddr[7:0]] <= wdata;
    220 	if (re)
    221 		ra <= mem[raddr[7:0]];
    222 end
    223 assign rdata = ra;
    224 `else
    225 
    226 `ifdef YOSYS
    227 SB_RAM40_4K #(
    228         .READ_MODE(0),
    229         .WRITE_MODE(0)
    230         )
    231 `else
    232 SB_RAM256x16
    233 `endif
    234 	sram_inst(
    235 	.RDATA(rdata),
    236 	.RADDR(raddr[7:0]),
    237 	.RCLK(clk),
    238 	.RCLKE(1'b1),
    239 	.RE(re),
    240 	.WADDR(waddr[7:0]),
    241 	.WDATA(wdata),
    242 	.WCLK(clk),
    243 	.WCLKE(1'b1),
    244 	.WE(we),
    245 	.MASK(16'b0)
    246 	);
    247 `endif
    248 
    249 endmodule