首页 > 代码库 > omsp430ikmcu外设

omsp430ikmcu外设

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   =   16h020;   

// Register addresses
parameter          GPIOIN   = BASIC_ADDR + 9h000;
parameter          GPIOOUT  = BASIC_ADDR + 9h001;
parameter          GPIODIR  = BASIC_ADDR + 9h002;
parameter          GPIOIFG  = BASIC_ADDR + 9h003;
parameter          GPIOIES  = BASIC_ADDR + 9h004;
parameter          GPIOIE   = BASIC_ADDR + 9h005;
//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   = (256h1 << (GPIOIN  /2));
    (GPIOOUT    /2):   reg_dec   = (256h1 << (GPIOOUT /2));
    (GPIODIR    /2):   reg_dec   = (256h1 << (GPIODIR /2));
    (GPIOIFG    /2):   reg_dec   = (256h1 << (GPIOIFG /2));
    (GPIOIES    /2):   reg_dec   = (256h1 << (GPIOIES /2));
    (GPIOIE     /2):   reg_dec   = (256h1 << (GPIOIE  /2));
//    (GPIOSEL    /2):   reg_dec   = (256‘h1 << (GPIOSEL /2));
    default    :   reg_dec   = {256{1b0}};
  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 <=  8hb0;
  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 <=  8h00;
  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 <=  8h00;
  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 <=  8h00;
  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 <=  8h00;
  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:    wuzhangquan@foxmail.com
//  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   =   16h040;   

// Register addresses
parameter   UTXBUF  = BASIC_ADDR + 9h000;
parameter   URXBUF  = BASIC_ADDR + 9h001;
parameter   UCTL    = BASIC_ADDR + 9h002;
parameter   UFLAG   = BASIC_ADDR + 9h003;
parameter   UBR0    = BASIC_ADDR + 9h004;
parameter   UBR1    = BASIC_ADDR + 9H005;

//============================================================================
// 2)  REGISTER DECODER
//============================================================================

// Register address decode
reg  [255:0]  reg_dec; 
always @(per_addr)
  case (per_addr)
    (UTXBUF /2):   reg_dec   = (256h1 << (UTXBUF /2));
    (URXBUF /2):   reg_dec   = (256h1 << (URXBUF /2));
    (UCTL   /2):   reg_dec   = (256h1 << (UCTL /2));
    (UFLAG  /2):   reg_dec   = (256h1 << (UFLAG /2));
    (UBR0   /2):   reg_dec   = (256h1 << (UBR0  /2));
    (UBR1   /2):   reg_dec   = (256h1 << (UBR1  /2));

    default    :   reg_dec   = {256{1b0}};
  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 <=  8h0a;
  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 <=  8hb0;
  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 <=  8h00;
  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 <=  8h00;
  else if (uflag_wr) uflag <=  uflag_nxt & 8h03;
  else                uflag <= {6b0,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 <=  8h00;
  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 <=  8h00;
  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 =http://www.mamicode.com/ 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 + 1b1;


//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  <=  1b0;
      txd <=  1b1;
      bitcnt  <=  4h0;
      txdata_reg  <=  10h3ff;
    end
  else if(txwr)   //检测启动信号   
    begin
      txbusy  <=  1b1;
      txd     <=  1b1;
      bitcnt  <=  4h0;
      txdata_reg  <=  {1b1,txdata,1b0};
    end
  else if(txtick)
    begin
      //4‘HB == STOPBIT=2; 4‘HA==STOPBIT==1
      if(bitcnt<4hB) bitcnt  <=  bitcnt + 1b1;  
      else            txbusy  <=  1b0;
      txd         <=  txdata_reg[0];
      txdata_reg  <=  {1b1,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 + 1b1;

//  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 <=  1b1;
  else if(rxd_samp==4hf) rxd_deb <=  1b1;
  else if(rxd_samp==4h0) rxd_deb <=  1b0;

//============================================
//  接收控制
//============================================
always @(posedge clk or negedge rstn)
  if(!rstn)
    begin
      rxbusy  <=  1b0;
      bitcnt  <=  4h0;
      rxdata_r  <=  9h0;
      rxdata  <=  0;
    end
  else if(!rxd_deb & !rxbusy)
    begin
      rxbusy  <=  1b1;
      bitcnt  <=  4h0;
    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==4h9)
        begin
          rxdata  <=  rxdata_r[8:1];
          bitcnt  <=  4h0;
          rxbusy  <=  4h0;
        end
      else
          bitcnt  <=  bitcnt + 1b1;
    end
always @(posedge clk or negedge rstn)
  if(!rstn) rxbusy_r  <=  1b0;
  else      rxbusy_r  <=  rxbusy;

assign  rxvalid = rxbusy_r & !rxbusy;

endmodule
uart_rx

 

omsp430ikmcu外设