`timescale 1ns / 1ps `define clock cpuclk `define clkfreq 25000000 //`define clock clk //`define clkfreq 100000000 //`define clock clk_1hz `define ENABLE_VGAFB `define ENABLE_MICROSD module top( input wire clk, input wire rst, output wire led0, input wire uart_txd_in, output wire uart_rxd_out `ifdef ENABLE_VGAFB , output wire [3:0] VGA_R, output wire [3:0] VGA_G, output wire [3:0] VGA_B, output wire VGA_HS_O, output wire VGA_VS_O `endif `ifdef ENABLE_MICROSD , output wire sd_cs_n, output wire sd_mosi, input wire sd_miso, output wire sd_sck, input wire sd_cd `endif ); reg [31:0] counter; localparam ADDR_WIDTH = 32, WIDTH = 32, ROMADDR_WIDTH = 11, IOADDR_WIDTH = 11, IOADDR_SEL = 4; wire [ADDR_WIDTH-1:0] mem_addr; wire [WIDTH-1:0] mem_read_data; wire [WIDTH-1:0] mem_write_data; (* KEEP *) wire mem_wait; (* KEEP *) wire mem_read_enable; (* KEEP *) wire mem_write_enable; (* KEEP *) wire io_enable; wire [WIDTH-1:0] io_rd_data; wire [IOADDR_SEL-1:0] io_slot = mem_addr[IOADDR_WIDTH-1:IOADDR_WIDTH-IOADDR_SEL]; wire irq; // assign led0 = mem_wait; wire [WIDTH-1:0] debug_data1, debug_data2, debug_data3, debug_data4, debug_data5, debug_data6; assign led0 = debug_data6[0]; wire cpuclk, cpuclk_locked; wire dram_refclk200; wire pixclk = cpuclk; cpu_clkgen cpuclk_0(~rst, clk, cpuclk, cpuclk_locked); mem #(.ADDR_WIDTH(ADDR_WIDTH), .DATA_WIDTH(WIDTH)) mem0( .clk(`clock), .rst_n(rst), .addr(mem_addr), .data_out(mem_read_data), .read_enable(mem_read_enable), .data_in(mem_write_data), .write_enable(mem_write_enable), .io_enable(io_enable), .io_rd_data(io_rd_data), .mem_wait(mem_wait) ); `ifdef ENABLE_VGAFB localparam FB_ADDR_WIDTH = 14; wire [FB_ADDR_WIDTH-1:0] fb_rd_addr; wire [FB_ADDR_WIDTH-1:0] fb_wr_addr; wire [WIDTH-1:0] fb_rd_data; wire [WIDTH-1:0] fb_wr_data; wire fb_rd_en, fb_wr_en; wire fb_cs_en = io_enable && (io_slot == 2); assign fb_rd_en = fb_cs_en && mem_read_enable; assign fb_wr_en = fb_cs_en && mem_write_enable; assign fb_wr_data = mem_write_data; vgafb vgafb0(`clock, pixclk, rst, mem_addr[3:0], fb_rd_data, fb_wr_data, fb_rd_en, fb_wr_en, VGA_HS_O, VGA_VS_O, VGA_R, VGA_G, VGA_B); `endif // SPI SD card controller ------------------------------------------------------------------- `ifdef ENABLE_MICROSD wire [7:0] spi_tx_data; (*KEEP*) wire [7:0] spi_rx_data; wire spi_tx_ready; // ready to transmit new data wire spi_tx_empty; // tx fifo is empty wire spi_rx_avail; // a byte has been received wire spi_rx_ovr; // receiver overrun wire spi_tx_write; // write strobe wire spi_rx_read; // read strobe (clears rx_avail) wire spi_card_detect; // true is card is present wire spi_card_changed; // card_detect signal has changed wire spi_card_busy; // card is busy (MISO/DO is 0) wire spi_ctrl_write; // set the following flags wire spi_rx_filter_en; // set to wait for start bit (1-to-0) when receiving wire spi_txrx_en; // enable transmitter and receiver wire spi_sclk_f_en; // enable spi clock without transceiver wire spi_sclk_div_wr; // set clock divider from tx_data wire spi_cs; // cs signal for spi controller wire [WIDTH-1:0] spi_rd_data; assign spi_cs = io_enable && (io_slot == 1); // spi read data: [ 0,...,0,cd,cc,cb,tr,te,ra,ro,d,d,d,d,d,d,d,d ] // cd = card detect, cc = card changed, cb = card busy, // tr = transmitter ready, te = tx fifo empty, // ra = received byte available, ro = receive overrun, d = received byte assign spi_rd_data = { {WIDTH-15{1'b0}}, spi_card_detect, spi_card_changed, spi_card_busy, spi_tx_ready, spi_tx_empty, spi_rx_avail, spi_rx_ovr, spi_rx_data }; // spi write data: [ 0,...,0,CW,CF,Cx,Cc,Cd,DR,DW,d,d,d,d,d,d,d,d ] // CW = control write, CF = enable receive filter, Cx = enable transceiver, // Cc = force spi clock on, Cd = write clock divider, // DR = read acknowledge, DW = data write, d = byte to be sent assign spi_ctrl_write = spi_cs && mem_write_enable && mem_write_data[14]; assign spi_rx_filter_en = mem_write_data[13]; assign spi_txrx_en = mem_write_data[12]; assign spi_sclk_f_en = mem_write_data[11]; assign spi_sclk_div_wr = spi_cs && mem_write_enable && mem_write_data[10]; assign spi_rx_read = mem_write_data[9]; assign spi_tx_write = spi_cs && mem_write_enable && mem_write_data[8]; assign spi_tx_data = mem_write_data[7:0]; sdspi sdspi0(.clk(`clock), .reset(~rst), .tx_data(spi_tx_data), .rx_data(spi_rx_data), .tx_ready(spi_tx_ready), .tx_empty(spi_tx_empty), .rx_avail(spi_rx_avail), .rx_ovr(spi_rx_ovr), .tx_write(spi_tx_write), .rx_read(spi_rx_read), .card_detect(spi_card_detect), .card_changed(spi_card_changed), .card_busy(spi_card_busy), // ctrl_write is used with rx_filter_en, txrx_en and spiclk_f_en .ctrl_write(spi_ctrl_write), .rx_filter_en(spi_rx_filter_en), .txrx_en(spi_txrx_en), .spiclk_f_en(spi_sclk_f_en), // .spiclk_div_wr(spi_sclk_div_wr), .sd_cs_n(sd_cs_n), .sd_mosi(sd_mosi), .sd_miso(sd_miso), .sd_sck(sd_sck), .sd_cd(sd_cd)); `endif // UART ----------------------------------------------------------------------- // uart write data: [ 0, 0, 0, 0, 0, T, C, 0, c, c, c, c, c, c, c, c ] // T = transmit enable, C = receiver clear, c = 8-bit-character // uart read data: [ 0, 0, 0, 0, 0, 0, A, B, c, c, c, c, c, c, c, c ] // A = char available, B = tx busy, c = 8-bit-character wire uart_cs = io_enable && (io_slot == 0); wire uart_tx_en = uart_cs && mem_write_enable && mem_write_data[10]; wire uart_rx_clear = uart_cs && mem_write_enable && mem_write_data[9]; wire uart_rx_avail; wire uart_rx_busy, uart_tx_busy; wire uart_err; wire [7:0] uart_rx_data; wire [7:0] uart_tx_data; wire [31:0] uart_baud = 32'd115200; wire [WIDTH-1:0] uart_rd_data; assign uart_tx_data = mem_write_data[7:0]; assign uart_rd_data = { {WIDTH-10{1'b1}}, uart_rx_avail, uart_tx_busy, uart_rx_data }; reg timer_tick; reg[23:0] tick_count; wire [1:0] irq_in = { timer_tick, uart_rx_avail }; wire [1:0] irqc_rd_data0; wire [WIDTH-1:0] irqc_rd_data = { tick_count, 6'b0, irqc_rd_data0 }; wire irqc_seten = mem_write_data[7]; wire irqc_cs = io_enable && (io_slot == 3); assign io_rd_data = (io_slot == 0) ? uart_rd_data : `ifdef ENABLE_MICROSD (io_slot == 1) ? spi_rd_data : `endif `ifdef ENABLE_VGAFB (io_slot == 2) ? fb_rd_data : `endif (io_slot == 3) ? irqc_rd_data: -1; buart #(.CLKFREQ(`clkfreq)) uart0(`clock, rst, uart_baud, uart_txd_in, uart_rxd_out, uart_rx_clear, uart_tx_en, uart_rx_avail, uart_tx_busy, uart_tx_data, uart_rx_data); // CPU ----------------------------------------------------------------- stackcpu cpu0(.clk(`clock), .rst(rst), .irq(irq), .addr(mem_addr), .data_in(mem_read_data), .read_enable(mem_read_enable), .data_out(mem_write_data), .write_enable(mem_write_enable), .mem_wait(mem_wait), .led1(led1), .led2(led2), .led3(led3), .debug_out1(debug_data1), .debug_out2(debug_data2), .debug_out3(debug_data3), .debug_out4(debug_data4), .debug_out5(debug_data5), .debug_out6(debug_data6)); // Interrupt Controller irqctrl irqctrl0(`clock, irq_in, irqc_cs, mem_write_enable, irqc_seten, irqc_rd_data0, irq); // count clock ticks // generate interrupt every 20nth of a second always @ (posedge `clock) begin counter <= counter + 1; if (counter >= (`clkfreq/20)) begin counter <= 0; timer_tick <= 1; tick_count <= tick_count + 1'b1; end else begin timer_tick <= 0; end end endmodule