GPIO
module gpio ( input [7:0] gpio_din, output [7:0] gpio_dout, output [7:0] gpio_dir, output irq_gpio, // OUTPUTs //========= output [15:0] per_dout, // Peripheral data output // INPUTs //========= input mclk, // Main system clock input [7:0] per_addr, // Peripheral address input [15:0] per_din, // Peripheral data input input per_en, // Peripheral enable (high active) input [1:0] per_wen, // Peripheral write enable (high active) input puc // Main system reset ); //============================================================================= // 1) PARAMETER DECLARATION //============================================================================= parameter BASIC_ADDR = 16‘h020; // Register addresses parameter GPIOIN = BASIC_ADDR + 9‘h000; parameter GPIOOUT = BASIC_ADDR + 9‘h001; parameter GPIODIR = BASIC_ADDR + 9‘h002; parameter GPIOIFG = BASIC_ADDR + 9‘h003; parameter GPIOIES = BASIC_ADDR + 9‘h004; parameter GPIOIE = BASIC_ADDR + 9‘h005; //parameter GPIOSEL = BASIC_ADDR + 9‘h006; //============================================================================ // 2) REGISTER DECODER //============================================================================ // Register address decode reg [255:0] reg_dec; always @(per_addr) case (per_addr) (GPIOIN /2): reg_dec = (256‘h1 << (GPIOIN /2)); (GPIOOUT /2): reg_dec = (256‘h1 << (GPIOOUT /2)); (GPIODIR /2): reg_dec = (256‘h1 << (GPIODIR /2)); (GPIOIFG /2): reg_dec = (256‘h1 << (GPIOIFG /2)); (GPIOIES /2): reg_dec = (256‘h1 << (GPIOIES /2)); (GPIOIE /2): reg_dec = (256‘h1 << (GPIOIE /2)); // (GPIOSEL /2): reg_dec = (256‘h1 << (GPIOSEL /2)); default : reg_dec = {256{1‘b0}}; endcase // Read/Write probes wire reg_lo_write = per_wen[0] & per_en; wire reg_hi_write = per_wen[1] & per_en; wire reg_read = ~|per_wen & per_en; // Read/Write vectors wire [255:0] reg_hi_wr = reg_dec & {256{reg_hi_write}}; wire [255:0] reg_lo_wr = reg_dec & {256{reg_lo_write}}; wire [255:0] reg_rd = reg_dec & {256{reg_read}}; //============================================================================ // 3) REGISTERS //============================================================================ // GPIOIN Register //----------------- reg [7:0] gpioin; reg [7:0] gpio_din_s; always @(posedge mclk) gpio_din_s <= gpio_din; always @(posedge mclk) gpioin <= gpio_din_s; // GPIOOUT Register //----------------- reg [7:0] gpioout; wire gpioout_wr = GPIOOUT[0] ? reg_hi_wr[GPIOOUT/2] : reg_lo_wr[GPIOOUT/2]; wire [7:0] gpioout_nxt = GPIOOUT[0] ? per_din[15:8] : per_din[7:0]; always @ (posedge mclk or posedge puc) if (puc) gpioout <= 8‘hb0; else if (gpioout_wr) gpioout <= gpioout_nxt; assign gpio_dout = gpioout; // GPIODIR Register //----------------- reg [7:0] gpiodir; wire gpiodir_wr = GPIODIR[0] ? reg_hi_wr[GPIODIR/2] : reg_lo_wr[GPIODIR/2]; wire [7:0] gpiodir_nxt = GPIODIR[0] ? per_din[15:8] : per_din[7:0]; always @ (posedge mclk or posedge puc) if (puc) gpiodir <= 8‘h00; else if (gpiodir_wr) gpiodir <= gpiodir_nxt; assign gpio_dir = gpiodir; // GPIOIFG Register //----------------- reg [7:0] gpioifg; wire [7:0] gpioifg_set; wire gpioifg_wr = GPIOIFG[0] ? reg_hi_wr[GPIOIFG/2] : reg_lo_wr[GPIOIFG/2]; wire [7:0] gpioifg_nxt = GPIOIFG[0] ? per_din[15:8] : per_din[7:0]; always @ (posedge mclk or posedge puc) if (puc) gpioifg <= 8‘h00; else if (gpioifg_wr) gpioifg <= gpioifg_nxt | gpioifg_set; else gpioifg <= gpioifg | gpioifg_set; // GPIOIES Register //---------------- reg [7:0] gpioies; wire gpioies_wr = GPIOIES[0] ? reg_hi_wr[GPIOIES/2] : reg_lo_wr[GPIOIES/2]; wire [7:0] gpioies_nxt = GPIOIES[0] ? per_din[15:8] : per_din[7:0]; always @ (posedge mclk or posedge puc) if (puc) gpioies <= 8‘h00; else if (gpioies_wr) gpioies <= gpioies_nxt; // GPIOIE Register //---------------- reg [7:0] gpioie; wire gpioie_wr = GPIOIE[0] ? reg_hi_wr[GPIOIE/2] : reg_lo_wr[GPIOIE/2]; wire [7:0] gpioie_nxt = GPIOIE[0] ? per_din[15:8] : per_din[7:0]; always @ (posedge mclk or posedge puc) if (puc) gpioie <= 8‘h00; else if (gpioie_wr) gpioie <= gpioie_nxt; assign gpioifg_set = { gpioies[7]? (gpioin[7] & ~gpio_din[7]) : (~gpioin[7] & gpio_din[7]), gpioies[6]? (gpioin[6] & ~gpio_din[6]) : (~gpioin[6] & gpio_din[6]), gpioies[5]? (gpioin[5] & ~gpio_din[5]) : (~gpioin[5] & gpio_din[5]), gpioies[4]? (gpioin[4] & ~gpio_din[4]) : (~gpioin[4] & gpio_din[4]), gpioies[3]? (gpioin[3] & ~gpio_din[3]) : (~gpioin[3] & gpio_din[3]), gpioies[2]? (gpioin[2] & ~gpio_din[2]) : (~gpioin[2] & gpio_din[2]), gpioies[1]? (gpioin[1] & ~gpio_din[1]) : (~gpioin[1] & gpio_din[1]), gpioies[0]? (gpioin[0] & ~gpio_din[0]) : (~gpioin[0] & gpio_din[0]) }; assign irq_gpio = |(gpioie & gpioifg); //============================================================================ // 4) DATA OUTPUT GENERATION //============================================================================ // Data output mux wire [15:0] gpioin_rd = (gpioin & {8{reg_rd[GPIOIN/2]}}) << (8 & {4{GPIOIN[0]}}); wire [15:0] gpioout_rd = (gpioout & {8{reg_rd[GPIOOUT/2]}}) << (8 & {4{GPIOOUT[0]}}); wire [15:0] gpiodir_rd = (gpiodir & {8{reg_rd[GPIODIR/2]}}) << (8 & {4{GPIODIR[0]}}); wire [15:0] gpioifg_rd = (gpioifg & {8{reg_rd[GPIOIFG/2]}}) << (8 & {4{GPIOIFG[0]}}); assign per_dout = gpioin_rd | gpioout_rd | gpiodir_rd | gpioifg_rd; endmodule // periph_8b
uart
////////////////////////////////////////////////// // Company: XL // Author: WuZhangQuan // Email: [email protected] // Module Name: // Targe Devices: // Revision: v1.0 ////////////////////////////////////////////////// module uart ( output txd, input rxd, // OUTPUTs //========= output [15:0] per_dout, // Peripheral data output // INPUTs //========= input mclk, // Main system clock input [7:0] per_addr, // Peripheral address input [15:0] per_din, // Peripheral data input input per_en, // Peripheral enable (high active) input [1:0] per_wen, // Peripheral write enable (high active) input puc // Main system reset ); //============================================================================= // 1) PARAMETER DECLARATION //============================================================================= parameter BASIC_ADDR = 16‘h040; // Register addresses parameter UTXBUF = BASIC_ADDR + 9‘h000; parameter URXBUF = BASIC_ADDR + 9‘h001; parameter UCTL = BASIC_ADDR + 9‘h002; parameter UFLAG = BASIC_ADDR + 9‘h003; parameter UBR0 = BASIC_ADDR + 9‘h004; parameter UBR1 = BASIC_ADDR + 9‘H005; //============================================================================ // 2) REGISTER DECODER //============================================================================ // Register address decode reg [255:0] reg_dec; always @(per_addr) case (per_addr) (UTXBUF /2): reg_dec = (256‘h1 << (UTXBUF /2)); (URXBUF /2): reg_dec = (256‘h1 << (URXBUF /2)); (UCTL /2): reg_dec = (256‘h1 << (UCTL /2)); (UFLAG /2): reg_dec = (256‘h1 << (UFLAG /2)); (UBR0 /2): reg_dec = (256‘h1 << (UBR0 /2)); (UBR1 /2): reg_dec = (256‘h1 << (UBR1 /2)); default : reg_dec = {256{1‘b0}}; endcase // Read/Write probes wire reg_lo_write = per_wen[0] & per_en; wire reg_hi_write = per_wen[1] & per_en; wire reg_read = ~|per_wen & per_en; // Read/Write vectors wire [255:0] reg_hi_wr = reg_dec & {256{reg_hi_write}}; wire [255:0] reg_lo_wr = reg_dec & {256{reg_lo_write}}; wire [255:0] reg_rd = reg_dec & {256{reg_read}}; //============================================================================ // 3) REGISTERS //============================================================================ // UTXBUF Register //----------------- reg [7:0] utxbuf; wire utxbuf_wr = UTXBUF[0] ? reg_hi_wr[UTXBUF/2] : reg_lo_wr[UTXBUF/2]; wire [7:0] utxbuf_nxt = UTXBUF[0] ? per_din[15:8] : per_din[7:0]; always @ (posedge mclk or posedge puc) if (puc) utxbuf <= 8‘h0a; else if (utxbuf_wr) utxbuf <= utxbuf_nxt; // URXBUF Register //----------------- reg [7:0] urxbuf; wire [7:0] rxdata; wire urxbuf_wr = URXBUF[0] ? reg_hi_wr[URXBUF/2] : reg_lo_wr[URXBUF/2]; wire [7:0] urxbuf_nxt = URXBUF[0] ? per_din[15:8] : per_din[7:0]; always @ (posedge mclk or posedge puc) if (puc) urxbuf <= 8‘hb0; else urxbuf <= rxdata; // else if (urxbuf_wr) urxbuf <= urxbuf_nxt; // UCTL Register //----------------- reg [7:0] uctl; wire uctl_wr = UCTL[0] ? reg_hi_wr[UCTL/2] : reg_lo_wr[UCTL/2]; wire [7:0] uctl_nxt = UCTL[0] ? per_din[15:8] : per_din[7:0]; always @ (posedge mclk or posedge puc) if (puc) uctl <= 8‘h00; else if (uctl_wr) uctl <= uctl_nxt; // UFLAG Register // bit1: uart tx busy // bit0: rx byte flag //----------------- reg [7:0] uflag; wire rxvalid; wire txbusy; wire uflag_wr = UFLAG[0] ? reg_hi_wr[UFLAG/2] : reg_lo_wr[UFLAG/2]; wire [7:0] uflag_nxt = UFLAG[0] ? per_din[15:8] : per_din[7:0]; always @ (posedge mclk or posedge puc) if (puc) uflag <= 8‘h00; else if (uflag_wr) uflag <= uflag_nxt & 8‘h03; else uflag <= {6‘b0,txbusy,uflag[0] | rxvalid}; // UBR0 Register //----------------- reg [7:0] ubr0; wire ubr0_wr = UBR0[0] ? reg_hi_wr[UBR0/2] : reg_lo_wr[UBR0/2]; wire [7:0] ubr0_nxt = UBR0[0] ? per_din[15:8] : per_din[7:0]; always @ (posedge mclk or posedge puc) if (puc) ubr0 <= 8‘h00; else if (ubr0_wr) ubr0 <= ubr0_nxt; // UBR1 Register //----------------- reg [7:0] ubr1; wire ubr1_wr = UBR1[0] ? reg_hi_wr[UBR1/2] : reg_lo_wr[UBR1/2]; wire [7:0] ubr1_nxt = UBR1[0] ? per_din[15:8] : per_din[7:0]; always @ (posedge mclk or posedge puc) if (puc) ubr1 <= 8‘h00; else if (ubr1_wr) ubr1 <= ubr1_nxt; //============================================================================ // 4) DATA OUTPUT GENERATION //============================================================================ // Data output mux wire [15:0] utxbuf_rd = (utxbuf & {8{reg_rd[UTXBUF/2]}}) << (8 & {4{UTXBUF[0]}}); wire [15:0] urxbuf_rd = (urxbuf & {8{reg_rd[URXBUF/2]}}) << (8 & {4{URXBUF[0]}}); wire [15:0] uctl_rd = (uctl & {8{reg_rd[UCTL/2]}}) << (8 & {4{UCTL[0]}}); wire [15:0] uflag_rd = (uflag & {8{reg_rd[UFLAG/2]}}) << (8 & {4{UFLAG[0]}}); assign per_dout = utxbuf_rd | urxbuf_rd | uctl_rd | uflag_rd; wire [15:0] baudctr = {ubr1,ubr0}; reg txwr; always @(posedge mclk) txwr <= utxbuf_wr; wire [7:0] txdata = utxbuf; //==================================== // 串口发送模块 //==================================== uart_tx u_uart_tx ( .rstn (!puc ), .clk (mclk ), .baudctr (baudctr), //波特率设置 .txwr (txwr ), //发送使能 .txdata (txdata ), //待发送的暑假 .txbusy (txbusy ), .txd (txd ) ); //==================================== // 串口接收模块 //==================================== uart_rx u_uart_rx ( .rstn (!puc ), .clk (mclk ), .baudctr (baudctr ), .rxdata (rxdata ), .rxbusy ( ), .rxvalid (rxvalid ), .rxd (rxd ) ); endmodule
uart_tx
module uart_tx ( input rstn, input clk, input [15:0] baudctr, //波特率设置 input txwr, //发送使能 input [7:0] txdata, //待发送的暑假 output reg txbusy, output reg txd ); reg [15:0] baudcnt; //波特率产生计数器 wire equ; //波特率计数器==波特率设置值 reg [3:0] bitcnt; //发送位计数器 reg [9:0] txdata_reg; //=========================================== // 波特率产生 // 当计数器==baudctr时,1bit 传输完成 //============================================ always @(posedge clk or negedge rstn) if(!rstn) baudcnt <= 0; else if(!txbusy) baudcnt <= 0; else if(equ) baudcnt <= 0; else baudcnt <= baudcnt + 1‘b1; //baudcnt计数等于baudctr时,1bit传输结束 assign equ = (baudcnt==baudctr); //wire txtick = (baudcnt == (baudctr>>1)); wire txtick = (baudcnt == 0) & txbusy; //============================================ // 发送控制 //============================================ always @(posedge clk or negedge rstn) if(!rstn) begin txbusy <= 1‘b0; txd <= 1‘b1; bitcnt <= 4‘h0; txdata_reg <= 10‘h3ff; end else if(txwr) //检测启动信号 begin txbusy <= 1‘b1; txd <= 1‘b1; bitcnt <= 4‘h0; txdata_reg <= {1‘b1,txdata,1‘b0}; end else if(txtick) begin //4‘HB == STOPBIT=2; 4‘HA==STOPBIT==1 if(bitcnt<4‘hB) bitcnt <= bitcnt + 1‘b1; else txbusy <= 1‘b0; txd <= txdata_reg[0]; txdata_reg <= {1‘b1,txdata_reg[9:1]}; end endmodule
uart_tx
uart_rx
module uart_rx ( input rstn, input clk, input [15:0] baudctr, //波特率设置 output reg [7:0] rxdata, //收到的数据 output reg rxbusy, //正在接收数据 output rxvalid, //收到数据指示 input rxd ); reg [15:0] baudcnt; //波特率产生计数器 wire equ; //波特率计数器==波特率设置值 wire rxtick; //采样点 reg [3:0] bitcnt; //发送位计数器 reg [3:0] rxd_samp; reg rxd_deb; reg [8:0] rxdata_r; reg rxbusy_r; //=========================================== // 波特率产生 // 当计数器==baudctr时,1bit 传输完成 //============================================ always @(posedge clk or negedge rstn) if(!rstn) baudcnt <= 0; else if(!rxbusy) baudcnt <= 0; else if(equ) baudcnt <= 0; else baudcnt <= baudcnt + 1‘b1; // baudctrl计算方式: // = clk时钟频率 / 波特率 // equ是baudcnt计数到baudctr时产生,表示1Bit所占的时间宽度 // 由于在数据中间采样最稳定,所以rxtick在baudcnt计数到baudctr // 一半的时候产生 //============================================================ assign equ = (baudcnt==baudctr); assign rxtick = (baudcnt==(baudctr>>1)); //在数据的中间采样 //============================================ // rxd 消抖 //============================================ always @(posedge clk) rxd_samp <= {rxd_samp[2:0],rxd}; always @(posedge clk or negedge rstn) if(!rstn) rxd_deb <= 1‘b1; else if(rxd_samp==4‘hf) rxd_deb <= 1‘b1; else if(rxd_samp==4‘h0) rxd_deb <= 1‘b0; //============================================ // 接收控制 //============================================ always @(posedge clk or negedge rstn) if(!rstn) begin rxbusy <= 1‘b0; bitcnt <= 4‘h0; rxdata_r <= 9‘h0; rxdata <= 0; end else if(!rxd_deb & !rxbusy) begin rxbusy <= 1‘b1; bitcnt <= 4‘h0; end else if(rxbusy & rxtick) begin //bitcnt: 0 1 2 3 4 5 6 7 8 9 A //data: start|D0|D1|D2|D3|D4|D5|D6|D7|STOP|STOP rxdata_r <= {rxd_deb,rxdata_r[8:1]}; if(bitcnt==4‘h9) begin rxdata <= rxdata_r[8:1]; bitcnt <= 4‘h0; rxbusy <= 4‘h0; end else bitcnt <= bitcnt + 1‘b1; end always @(posedge clk or negedge rstn) if(!rstn) rxbusy_r <= 1‘b0; else rxbusy_r <= rxbusy; assign rxvalid = rxbusy_r & !rxbusy; endmodule
uart_rx
时间: 2024-10-13 17:14:39