`timescale 1ns / 1ps // either define clock as clk (100MHz on Arty) // or as clk_1hz for debugging `define clock cpuclk //`define clkfreq 83333333 `define clkfreq 76923076 //`define clock clk //`define clkfreq 100000000 //`define clock clk_1hz `define ENABLE_VGAFB `define ENABLE_MICROSD `define ENABLE_TDRAUDIO module top( input wire clk, input wire rst, output wire led0, output wire led1, output wire led2, output wire led3, input wire uart_txd_in, output wire uart_rxd_out, // DDR3 SDRAM inout wire [15:0] ddr3_dq, inout wire [1:0] ddr3_dqs_n, inout wire [1:0] ddr3_dqs_p, output wire [13:0] ddr3_addr, output wire [2:0] ddr3_ba, output wire ddr3_ras_n, output wire ddr3_cas_n, output wire ddr3_we_n, output wire ddr3_reset_n, output wire [0:0] ddr3_ck_p, output wire [0:0] ddr3_ck_n, output wire [0:0] ddr3_cke, output wire [0:0] ddr3_cs_n, output wire [1:0] ddr3_dm, output wire [0:0] ddr3_odt `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 `ifdef ENABLE_TDRAUDIO , output wire amp2_ain, output wire amp2_gain, output wire amp2_shutdown_n `endif ); reg clk_1hz; reg [31:0] counter; localparam ADDR_WIDTH = 32, WIDTH = 32, ROMADDR_WIDTH = 11, IOADDR_WIDTH = 11, IOADDR_SEL = 4; (* KEEP *) 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; assign led0 = 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; wire cpuclk, cpuclk_locked; wire dram_refclk200; wire pixclk; cpu_clkgen cpuclk_0(~rst, clk, cpuclk, dram_refclk200, pixclk, cpuclk_locked); // DRAM -------------------------------------------------------------------------- wire [ADDR_WIDTH-1:0] dram_addr; wire [WIDTH-1:0] dram_read_data, dram_write_data; wire dram_read_enable, dram_write_enable, dram_wait; (* KEEP *) wire dram_read_ins; dram_bridge dram_bridge0 (dram_addr, dram_read_data, dram_write_data, dram_read_enable, dram_write_enable, dram_read_ins, dram_wait, rst, cpuclk, dram_refclk200, ddr3_dq, ddr3_dqs_n, ddr3_dqs_p, ddr3_addr, ddr3_ba, ddr3_ras_n, ddr3_cas_n, ddr3_we_n, ddr3_reset_n, ddr3_ck_p, ddr3_ck_n, ddr3_cke, ddr3_cs_n, ddr3_dm, ddr3_odt); 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), .dram_addr(dram_addr), .dram_read_data(dram_read_data), .dram_write_data(dram_write_data), .dram_read_enable(dram_read_enable), .dram_write_enable(dram_write_enable), .dram_wait(dram_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 }; wire audio_irq; 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); // audio controller `ifdef ENABLE_TDRAUDIO wire [WIDTH-1:0] tdraudio_wr_data; wire [WIDTH-1:0] tdraudio_rd_data; wire tdraudio_rd_en, tdraudio_wr_en; wire tdraudio_irq; wire tdraudio_cs_en = io_enable && (io_slot == 4); assign tdraudio_rd_en = tdraudio_cs_en && mem_read_enable; assign tdraudio_wr_en = tdraudio_cs_en && mem_write_enable; assign tdraudio_wr_data = mem_write_data; tdraudio tdraudio0(`clock, ~rst, mem_addr[6:0], tdraudio_rd_data, tdraudio_wr_data, tdraudio_rd_en, tdraudio_wr_en, tdraudio_irq, amp2_ain, amp2_gain, amp2_shutdown_n); assign audio_irq = tdraudio_irq; `endif // interrupt controller reg timer_tick; reg[23:0] tick_count; wire [2:0] irq_in = { audio_irq, timer_tick, uart_rx_avail }; wire [2:0] irqc_rd_data0; wire [WIDTH-1:0] irqc_rd_data = { tick_count, 5'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: `ifdef ENABLE_TDRAUDIO (io_slot == 4) ? tdraudio_rd_data: `endif -1; // CPU ----------------------------------------------------------------- stackcpu cpu0(.clk(`clock), .rst(rst), .irq(irq), .addr(mem_addr), .data_in(mem_read_data), .read_enable(mem_read_enable), .read_ins(dram_read_ins), .data_out(mem_write_data), .write_enable(mem_write_enable), .mem_wait(mem_wait), .debug1(led1), .debug2(led2), .debug3(led3)); // 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