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

📄 vspi.v

📁 Verilog HDL的程式
💻 V
📖 第 1 页 / 共 2 页
字号:
wire    shift_clk_negedge; //  negative edge of SCK
wire    shift_negative_edge_nxt; 
reg     shift_negative_edge; 
wire    shift_datain; 
wire    shift_dataout; 
reg     slvsel_r1; 
reg     slvsel_r2; 
reg     slvsel_r3; //  synchronizers
wire    spi_go; //  begin a transfer
//  slave select register
reg     [7:0] ssel; 
//  status register
wire    [7:0] status; 
//  TX has completed, TX_RUN will go low
wire    tx_end; 
reg     tx_run; //  tx is running
wire    tx_start; 
// -------------------------------------------------------------
reg     tx_start_r1; 
// ---------ARCHITECTURE rtl-----------
//  required for synopsys
//  # bits in a byte
assign 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 0 & write == 1'b 0 & 
	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 0)
      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 0)
      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
   end

assign 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=1
assign shift_dataout = phase == 1'b 1 ? shift_negative_edge : 
	shift_reg[7]; 
//  insert the neg DFF in phase=0
assign 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 running
always @(posedge clk)
   begin : tr_proc
   if (rst == 1'b 0)
      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 0)
//  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 counter
assign 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 0)
//  sync reset
      begin
      ctl_reg <= 8'b 00000000;	
      end
   else
      begin
      if (chip_sel == 1'b 0 & write == 1'b 0 & 
	addr == 2'b 01)
//  load
         begin
         ctl_reg <= datain;	
         end
      end
   end
//  map the control register to more meaningfull names
assign 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 0)
//  sync reset
      begin
      ssel <= 8'b 00000000;	
      end
   else
      begin
      if (chip_sel == 1'b 0 & write == 1'b 0 & 
	addr == 2'b 11)
//  load
         begin
         ssel <= datain;	
         end
      end
   end

assign slvselo = ssel[4:0]; //  drive the port
assign slvsele = master_mode; 
// -------Collision flag bit---------------------------
always @(posedge clk)
   begin : cf_proc
   if (rst == 1'b 0)
      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 0 & write == 1'b 0 & 
	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 0)
      begin
      oflow <= 1'b 0;	
      end
   else
      begin
      if (chip_sel == 1'b 0 & write == 1'b 0 & 
	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 0 & write == 1'b 0 & 
	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 0)
      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 )
*/
	  else
         begin
         irq_flag <= 1'b 0;	
         end
      end
   end

assign 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
//  dvd
assign 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 register
assign 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 + -