⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vspi.v

📁 有关SPI的vhdl实现。包括SPI官方协议
💻 V
📖 第 1 页 / 共 2 页
字号:
reg     [7:0] shift_reg; wire    shift_clk; wire    shift_clk_negedge; //  negative edge of SCKwire    shift_negative_edge_nxt; reg     shift_negative_edge; wire    shift_datain; wire    shift_dataout; reg     slvsel_r1; reg     slvsel_r2; reg     slvsel_r3; //  synchronizerswire    spi_go; //  begin a transfer//  slave select registerreg     [7:0] ssel; //  status registerwire    [7:0] status; //  TX has completed, TX_RUN will go lowwire    tx_end; reg     tx_run; //  tx is runningwire    tx_start; // -------------------------------------------------------------reg     tx_start_r1; // ---------ARCHITECTURE rtl-----------//  required for synopsys//  # bits in a byteassign mosio = mosie_lcl == 1'b 1 & open_drain == 1'b 0 ? shift_dataout : 	1'b 0; //  drive low when open drain enabled.assign mosie = open_drain == 1'b 0 ? mosie_lcl : 	mosie_lcl == 1'b 1 & shift_dataout == 1'b 0 ? 1'b 1 : 	1'b 0; assign misoo = misoe_lcl == 1'b 1 & open_drain == 1'b 0 ? shift_dataout : 	1'b 0; //  drive low when open drain enabled.assign misoe = open_drain == 1'b 0 ? misoe_lcl : 	misoe_lcl == 1'b 1 & shift_dataout == 1'b 0 ? 1'b 1 : 	1'b 0; assign misoe_lcl = master_mode == 1'b 0 & slvsel == 1'b 1 ? 1'b 1 : 	1'b 0; //  spi_go initiates a transfer - A write to the DOUT reg in master//  mode ignore the CPU write if we're already running.assign mosie_lcl = master_mode == 1'b 1 ? 1'b 1 : 	1'b 0; assign spi_go = chip_sel == 1'b 1 & write == 1'b 1 & 	addr == 2'b 00 & tx_run == 1'b 0 & 	slvsel_r3 == 1'b 0 ? 1'b 1 : 	1'b 0; // -----------Shift register----------------always @(posedge clk)   begin : sr_proc   if (rst == 1'b 1)      begin      shift_reg <= 8'b 00000000;	//  sync reset      end   else      begin      if (spi_go == 1'b 1)//  don't reload while running         begin         shift_reg <= datain;	//  load with data from CPU         end      else if (shift_clk == 1'b 1 )         begin         shift_reg <= {shift_reg[6:0], shift_datain};	         end      end   end// --------Hold time register--------------always @(posedge clk)//  negative edge pipeline DFF   begin : neg_proc   if (rst == 1'b 1)      begin      shift_negative_edge <= 1'b 0;	//  sync reset      end   else if (shift_clk_negedge == 1'b 1 )      begin      shift_negative_edge <= shift_negative_edge_nxt;	      end   else if (spi_go == 1'b 1 )      begin      shift_negative_edge <= datain[7];	//  preload for phase=0 mode      end   endassign shift_negative_edge_nxt = phase == 1'b 1 ? shift_reg[7] : 	master_mode == 1'b 1 ? misoi : 	mosii; //  add in the negative edge dff on phase=1assign shift_dataout = phase == 1'b 1 ? shift_negative_edge : 	shift_reg[7]; //  insert the neg DFF in phase=0assign shift_datain = phase == 1'b 0 ? shift_negative_edge : 	master_mode == 1'b 1 ? misoi : 	mosii; // -------------TX run------------------//  this bit is active while a transmit is runningalways @(posedge clk)   begin : tr_proc   if (rst == 1'b 1)      begin      tx_run <= 1'b 0;	//  sync reset      end   else      begin      if (tx_start == 1'b 1)         begin         tx_run <= 1'b 1;	         end      else if (tx_end == 1'b 1 )         begin         tx_run <= 1'b 0;	         end      end   end// -----------Bit counter for master mode----------------always @(posedge clk)   begin : bc_proc   if (rst == 1'b 1)//  sync reset      begin      bit_ctr <= 3'b 000;	      end   else      begin      if (tx_start == 1'b 1)         begin         bit_ctr <= ssel[7:5];	         end      else if (shift_clk == 1'b 1 )         begin         bit_ctr <= bit_ctr - 1'b 1;	         end      end   end//  bit counterassign tx_end = master_mode == 1'b 1 & bit_ctr == 3'b 001 & 	shift_clk == 1'b 1 & tx_run == 1'b 1 ? 1'b 1 : 	1'b 0; assign tx_start = master_mode == 1'b 1 & spi_go == 1'b 1 ? 1'b 1 : 	1'b 0; // -------Control Register----------------------always @(posedge clk)   begin : gjr_proc   if (rst == 1'b 1)//  sync reset      begin      ctl_reg <= 8'b 00000000;	      end   else      begin      if (chip_sel == 1'b 1 & write == 1'b 1 & 	addr == 2'b 01)//  load         begin         ctl_reg <= datain;	         end      end   end//  map the control register to more meaningfull namesassign master_mode = ctl_reg[1]; assign open_drain = ctl_reg[2]; assign polck = ctl_reg[3]; assign phase = ctl_reg[4]; assign sel_clk = ctl_reg[6:5]; // -------Slave Select Register-------------------------always @(posedge clk)   begin : s_proc   if (rst == 1'b 1)//  sync reset      begin      ssel <= 8'b 00000000;	      end   else      begin      if (chip_sel == 1'b 1 & write == 1'b 1 & 	addr == 2'b 11)//  load         begin         ssel <= datain;	         end      end   endassign slvselo = ssel[4:0]; //  drive the portassign slvsele = master_mode; // -------Collision flag bit---------------------------always @(posedge clk)   begin : cf_proc   if (rst == 1'b 1)      begin      col_flag <= 1'b 0;	      end   else      begin      if (master_mode == 1'b 1 & slvsel_r3 == 1'b 1)         begin         col_flag <= 1'b 1;	         end      else if (chip_sel == 1'b 1 & write == 1'b 1 & 	addr == 2'b 10 & datain[5] == 1'b 1 )         begin         col_flag <= 1'b 0;	         end      end   end// -------OFLOw flag bit------------------------------always @(posedge clk)   begin : o_proc   if (rst == 1'b 1)      begin      oflow <= 1'b 0;	      end   else      begin      if (chip_sel == 1'b 1 & write == 1'b 1 & 	addr == 2'b 00 & (tx_run == 1'b 1 | 	slvsel_r3 == 1'b 1))//  write to DOUT//  and we're busy         begin         oflow <= 1'b 1;	         end      else if (chip_sel == 1'b 1 & write == 1'b 1 & 	addr == 2'b 10 & datain[6] == 1'b 1 )         begin         oflow <= 1'b 0;	         end      end   end// -------IRQ flag bit------------------------------always @(posedge clk)   begin : elr_proc   if (rst == 1'b 1)      begin      irq_flag <= 1'b 0;	      end   else      begin      if (tx_end == 1'b 1 | slvsel_r2 == 1'b 0 & 	slvsel_r3 == 1'b 1)         begin         irq_flag <= 1'b 1;	         end      else if (chip_sel == 1'b 1 & write == 1'b 1 & 	addr == 2'b 10 & datain[7] == 1'b 1 )         begin         irq_flag <= 1'b 0;	         end      end   endassign irq = irq_flag & ctl_reg[7]; //  gate with the IRQENB bit.// --------------various pipeline flops---------always @(posedge clk)   begin : flops_proc   slvsel_r3 <= slvsel_r2;	   slvsel_r2 <= slvsel_r1;	//  synchronizers   slvsel_r1 <= slvsel;	   sck_r3 <= sck_r2;	   sck_r2 <= sck_r1;	//  synchronizers//  select the desired polarity of the slave clk   sck_r1 <= ~scki ^ polck;	   tx_start_r1 <= tx_start;	   end// --------------clock divider for clk generation-------//  create a 2x clock which creates 2 pulses.//  One for each edge of SCK.always @(posedge clk)   begin : dvd_proc   if (~(tx_run == 1'b 1 & master_mode == 1'b 1) | 	tx_end == 1'b 1)//  divider only runs when sending data      begin      dvd_ctr <= 5'b 00000;	      dvd2 <= 1'b 0;	      end   else      begin      if (dvd_ctr == 5'b 00000)         begin         if (sel_clk == 2'b 00)            begin            dvd_ctr <= 5'b 00011;	            end         else if (sel_clk == 2'b 01 )            begin            dvd_ctr <= 5'b 00111;	            end         else if (sel_clk == 2'b 10 )            begin            dvd_ctr <= 5'b 01111;	            end         else            begin            dvd_ctr <= 5'b 11111;	            end         if (tx_start_r1 == 1'b 0)            begin            dvd2 <= ~dvd2;	            end         end      else         begin         dvd_ctr <= dvd_ctr - 1'b 1;	         end      end   end//  dvdassign dvd_zero = dvd_ctr == 5'b 00000 ? 1'b 1 : 	1'b 0; //  TX_START_R1 prevents data from shifting on the first//  clock in POLCK=1 mode which we don't want.We only get//  7 clocks otherwise.assign shift_clk = master_mode == 1'b 1 ? dvd_zero & dvd2 & tx_run & 	~tx_start_r1 : 	sck_r2 & ~sck_r3; //  dataout multiplexor for register readback//  assemble the bits that make up the status registerassign shift_clk_negedge = master_mode == 1'b 1 ? dvd_zero & ~dvd2 & tx_run : 	~sck_r2 & sck_r3; assign status = {irq_flag, oflow, col_flag, 3'b 000, 	tx_run, slvsel_r3}; assign scke = master_mode; assign scko = dvd2 ^ polck; assign dataout = addr == 2'b 00 ? shift_reg : 	addr == 2'b 01 ? ctl_reg : 	addr == 2'b 10 ? status : 	addr == 2'b 11 ? ssel : 	8'b xxxxxxxx; endmodule // module vspi

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -