module multi_uart_ip #(parameter UART_GROUP = 2, // Number of UART groups UART_COUNT = 6, // Number of UART instances in each group UART_TOTAL = UART_GROUP * UART_COUNT ) ( // input [UART_TOTAL-1:0] uart_rxd, // output [UART_TOTAL-1:0] uart_txd, output tri0 SIM_CLK, inout [11:0] SIM_IO, inout SIM_IO_12, inout SIM_IO_13, inout SIM_IO_14, inout SIM_IO_15, input uart14_rx, output tri0 uart14_tx, input uart15_rx, output tri0 uart15_tx, output tri0 [3:0] ext_int_in, output tri0 [5:0] gpio_int_g0_in, output tri0 [5:0] gpio_int_g1_in, output tri0 rxd_12_ip_in, output tri0 rxd_13_ip_in, output tri0 rxd_14_ip_in, output tri0 rxd_15_ip_in, input txd_12_ip_out_data, input txd_12_ip_out_en, input txd_13_ip_out_data, input txd_13_ip_out_en, input txd_14_ip_out_data, input txd_14_ip_out_en, input txd_15_ip_out_data, input txd_15_ip_out_en, input txen_12_ip_out_data, input txen_12_ip_out_en, input txen_13_ip_out_data, input txen_13_ip_out_en, input txen_14_ip_out_data, input txen_14_ip_out_en, input txen_15_ip_out_data, input txen_15_ip_out_en, input sys_clock, input bus_clock, input resetn, input stop, input [1:0] mem_ahb_htrans, input mem_ahb_hready, input mem_ahb_hwrite, input [31:0] mem_ahb_haddr, input [2:0] mem_ahb_hsize, input [2:0] mem_ahb_hburst, input [31:0] mem_ahb_hwdata, output tri1 mem_ahb_hreadyout, output tri0 mem_ahb_hresp, output tri0 [31:0] mem_ahb_hrdata, output tri0 slave_ahb_hsel, output tri1 slave_ahb_hready, input slave_ahb_hreadyout, output tri0 [1:0] slave_ahb_htrans, output tri0 [2:0] slave_ahb_hsize, output tri0 [2:0] slave_ahb_hburst, output tri0 slave_ahb_hwrite, output tri0 [31:0] slave_ahb_haddr, output tri0 [31:0] slave_ahb_hwdata, input slave_ahb_hresp, input [31:0] slave_ahb_hrdata, output tri0 [3:0] ext_dma_DMACBREQ, output tri0 [3:0] ext_dma_DMACLBREQ, output tri0 [3:0] ext_dma_DMACSREQ, output tri0 [3:0] ext_dma_DMACLSREQ, input [3:0] ext_dma_DMACCLR, input [3:0] ext_dma_DMACTC, output tri0 [3:0] local_int ); reg [UART_TOTAL-1:0] uart_tx_busy; wire [UART_TOTAL-1:0] uart_rxd; reg [UART_TOTAL-1:0] uart_txd; assign uart_rxd = uart_tx_busy | SIM_IO; // 接收 genvar i; generate for (i = 0; i < UART_TOTAL; i = i + 1) begin : gen_sim_io assign SIM_IO[i] = uart_tx_busy[i] ? uart_txd[i] : 1'bz; // 发送 end endgenerate assign SIM_IO_12 = (txen_12_ip_out_en && txen_12_ip_out_data) ? (txd_12_ip_out_en ? txd_12_ip_out_data : 1'bz) : 1'bz; assign rxd_12_ip_in = (txen_12_ip_out_en && txen_12_ip_out_data) ? 1'bz : SIM_IO_12; assign SIM_IO_13 = (txen_13_ip_out_en && txen_13_ip_out_data) ? (txd_13_ip_out_en ? txd_13_ip_out_data : 1'bz) : 1'bz; assign rxd_13_ip_in = (txen_13_ip_out_en && txen_13_ip_out_data) ? 1'bz : SIM_IO_13; // assign SIM_IO_14 = (txen_14_ip_out_en && txen_14_ip_out_data) ? (txd_14_ip_out_en ? txd_14_ip_out_data : 1'bz) : 1'bz; // assign rxd_14_ip_in = (txen_14_ip_out_en && txen_14_ip_out_data) ? 1'bz : SIM_IO_14; assign SIM_IO_14 = (txen_14_ip_out_en && txen_14_ip_out_data) ? (txd_14_ip_out_en ? txd_14_ip_out_data : 1'bz) : 1'bz; assign rxd_14_ip_in = txen_14_ip_out_en ? ((txen_14_ip_out_data) ? 1'bz : SIM_IO_14) : uart14_rx; assign uart14_tx = (!txen_14_ip_out_en) ? txd_14_ip_out_data : 1'bz; assign SIM_IO_15 = (txen_15_ip_out_en && txen_15_ip_out_data) ? (txd_15_ip_out_en ? txd_15_ip_out_data : 1'bz) : 1'bz; assign rxd_15_ip_in = txen_15_ip_out_en ? ((txen_15_ip_out_data) ? 1'bz : SIM_IO_15) : uart15_rx; // assign uart15_tx = (!txen_15_ip_out_en) ? (txd_15_ip_out_en ? txd_15_ip_out_data : 1'bz) : 1'bz; assign uart15_tx = (!txen_15_ip_out_en) ? txd_15_ip_out_data : 1'bz; parameter DATA_WIDTH = 8; parameter FIFO_DEPTH = 1; wire [UART_TOTAL-1:0] tx_dma_clr; wire [UART_TOTAL-1:0] tx_dma_req; wire [UART_TOTAL-1:0] rx_dma_clr; wire [UART_TOTAL-1:0] rx_dma_req; wire [UART_TOTAL-1:0] interrupts; // Different ways to generate interrupts. // assign local_int = interrupts[3:0]; // assign ext_int_in = ~interrupts[7:4]; // External interrupts are active low. // assign gpio_int_in = interrupts[11:8]; assign gpio_int_g0_in = interrupts[ 0+:UART_COUNT]; assign gpio_int_g1_in = interrupts[UART_COUNT+:UART_COUNT]; // Only 4 DMA requests are available. Can be used for any UART instance. assign ext_dma_DMACBREQ = { tx_dma_req[1:0], rx_dma_req[1:0] }; assign { tx_dma_clr[1:0], rx_dma_clr[1:0] } = ext_dma_DMACCLR ; parameter APB_SEL_BITS = $clog2(UART_GROUP); parameter APB_ADDR_BITS = 12; parameter AHB_ADDR_BITS = APB_ADDR_BITS + APB_SEL_BITS; wire mem_apb_psel; wire mem_apb_penable; wire mem_apb_pwrite; wire [AHB_ADDR_BITS-1:0] mem_apb_paddr; wire [31:0] mem_apb_pwdata; wire [3:0] mem_apb_pstrb; wire [2:0] mem_apb_pprot; wire mem_apb_pready; wire mem_apb_pslverr; wire [31:0] mem_apb_prdata; wire [APB_ADDR_BITS-1:0] mem_apb_address = mem_apb_paddr[APB_ADDR_BITS-1:0]; wire [UART_GROUP-1:0] mem_apb_onehot = 1'b1 << (mem_apb_paddr >> APB_ADDR_BITS); wire [UART_GROUP-1:0] uart_apb_psel; wire [UART_GROUP-1:0] uart_apb_penable; wire [UART_GROUP-1:0] uart_apb_pwrite; wire [UART_GROUP*APB_ADDR_BITS-1:0] uart_apb_paddr; wire [UART_GROUP*32-1:0] uart_apb_pwdata; wire [UART_GROUP*32-1:0] uart_apb_prdata; wire [UART_GROUP-1:0] uart_apb_pready; wire [UART_GROUP-1:0] uart_apb_pslverr = 0; ahb2apb #(AHB_ADDR_BITS) u_ahb2apb( .reset (!resetn ), .ahb_clock (sys_clock ), .ahb_hmastlock(1'b0 ), .ahb_htrans (mem_ahb_htrans ), .ahb_hsel (1'b1 ), .ahb_hready (mem_ahb_hready ), .ahb_hwrite (mem_ahb_hwrite ), .ahb_haddr (mem_ahb_haddr[AHB_ADDR_BITS-1:0]), .ahb_hsize (mem_ahb_hsize ), .ahb_hburst (mem_ahb_hburst ), .ahb_hprot (4'b0011 ), .ahb_hwdata (mem_ahb_hwdata ), .ahb_hrdata (mem_ahb_hrdata ), .ahb_hreadyout(mem_ahb_hreadyout ), .ahb_hresp (mem_ahb_hresp ), .apb_clock (bus_clock ), .apb_psel (mem_apb_psel ), .apb_penable (mem_apb_penable ), .apb_pwrite (mem_apb_pwrite ), .apb_paddr (mem_apb_paddr ), .apb_pwdata (mem_apb_pwdata ), .apb_pstrb (mem_apb_pstrb ), .apb_pprot (mem_apb_pprot ), .apb_pready (mem_apb_pready ), .apb_pslverr (mem_apb_pslverr ), .apb_prdata (mem_apb_prdata ) ); apb_mux #(UART_GROUP, APB_ADDR_BITS) u_apb_mux( .apb_clock (bus_clock ), .apb_resetn (resetn ), .apb_in_psel (mem_apb_psel ), .apb_in_penable (mem_apb_penable ), .apb_in_pwrite (mem_apb_pwrite ), .apb_in_paddr (mem_apb_address ), .apb_in_pwdata (mem_apb_pwdata ), .apb_in_prdata (mem_apb_prdata ), .apb_in_pready (mem_apb_pready ), .apb_in_pslverr (mem_apb_pslverr ), .apb_out_psel (uart_apb_psel ), .apb_out_penable(uart_apb_penable ), .apb_out_pwrite (uart_apb_pwrite ), .apb_out_paddr (uart_apb_paddr ), .apb_out_pwdata (uart_apb_pwdata ), .apb_out_prdata (uart_apb_prdata ), .apb_out_pready (uart_apb_pready ), .apb_out_pslverr(uart_apb_pslverr ), .apb_select (mem_apb_onehot ) ); multi_uart #(.CNT(UART_COUNT), .DATA_WIDTH(DATA_WIDTH), .FIFO_DEPTH(FIFO_DEPTH)) u_uart[UART_GROUP-1:0]( .apb_clock (bus_clock ), .apb_resetn (resetn ), .apb_psel (uart_apb_psel ), .apb_penable(uart_apb_penable), .apb_pwrite (uart_apb_pwrite ), .apb_paddr (uart_apb_paddr ), .apb_pwdata (uart_apb_pwdata ), .apb_prdata (uart_apb_prdata ), .apb_pready (uart_apb_pready ), .uart_txd (uart_txd ), .uart_rxd (uart_rxd ), .tx_dma_clr (tx_dma_clr ), .tx_dma_req (tx_dma_req ), .rx_dma_clr (rx_dma_clr ), .rx_dma_req (rx_dma_req ), .interrupts (interrupts ), .uart_tx_busy(uart_tx_busy ) ); assign slave_ahb_hready = 1'b1; // 串口clk时钟1.5MHz(对应波特率4000) // 串口clk时钟15MHz (对应波特率40000) parameter SYSCLK_FREQ = 240_000_000; parameter SIMCLK_FREQ = 15_000_000; parameter SIM_CLK_PER = (SYSCLK_FREQ/SIMCLK_FREQ/2); reg [7:0] sim_clk_cnt; reg sim_clk_reg; always @(posedge sys_clock or negedge resetn) begin if (!resetn) begin sim_clk_cnt <= 8'h0; sim_clk_reg <= 8'h0; end else if (sim_clk_cnt < (SIM_CLK_PER - 1)) begin sim_clk_cnt <= sim_clk_cnt + 1'b1; end else begin sim_clk_reg <= !sim_clk_reg; sim_clk_cnt <= 8'h0; end end assign SIM_CLK = sim_clk_reg; endmodule