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

📄 spi.v

📁 SPI to parallel verilog source code
💻 V
字号:
`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Author:         Till Harbaum <till@harbaum.org>// Create Date:    20:12:16 08/24/2006 // Project Name:   spi2cf// Target Devices: xc9572xl// Tool versions:  Webpack ISE 8.2// Description:    SPI to CF converter for use with Prism2 WLAN CF card// URL:            http://www.harbaum.org/till/spi2cf// License:        GPL////////////////////////////////////////////////////////////////////////////////////// CPLD version number`define VERSION 16'h0106`define VERSION_HI (`VERSION >> 8)`define VERSION_LO (`VERSION & 255)// commands`define GET_ID     0`define SET_ADDR   1`define REG_READ   2 `define REG_WRITE  3`define IO_READ    4`define IO_WRITE   5`define MEM_READ   6`define MEM_WRITE  7module spi(SS, SCK, SIN, EN, SOUT, INT, CFRST, LED, ADDRESS, DATA, REG, CE, OE, WE, IORD, IOWR, CD);	// interface to avr	input SS;   input SCK;   input SIN;	input EN;   output SOUT;	 	output INT;	// interface to cf card	output [10:0] ADDRESS;	inout [7:0] DATA;	output CE, OE, REG, WE;	output CFRST;	output LED;	output IORD, IOWR;	input CD;		// used to store incoming command	reg [2:0] cmd_reg;											 	// to determine end of byte	reg [2:0] bit_counter;	// keep track of transmission	reg [1:0] state;	reg addr_inc;	// address latch	reg [15:0] address_reg;    // only 11 actually are used as address lines	reg [7:0] data_reg;	reg [7:0] data_out_reg;	reg cf_ce, cf_reg, cf_oe, cf_we;	reg cf_iord, cf_iowr;		// output shift register	reg [7:0] out_reg;
	reg [7:0] data_in_reg;	wire cmd_internal;	wire cmd_cf_write, cmd_cf_read;	// count bits to determine and of a byte	// reset counter if 	always @(negedge SCK or posedge SS)	begin		// clear state if not selected		if (SS) begin 			bit_counter <= 0;			state <= 0;			end		// count bits and bytes		else begin			bit_counter <= bit_counter + 1;			if(bit_counter == 7) begin				// one byte completed, advance state. state				// goes: 0->1->2->3->2->3->2...				state[0] <= !state[0];				state[1] <= state[0] || state[1];			end		end	end	// process the flag indicating that the address auto increment is enabled	always @(posedge SCK or posedge SS)	begin		// clear state if not selected		if (SS) begin			addr_inc <= 0;			end		else begin			// enable auto address modes in all modes that cause cf data transfers			// (these are all but the internal commands SET_ADDR and GET_ID)			if(!cmd_internal)				if(bit_counter == 7) 					if(cmd_cf_read || (cmd_cf_write && state >= 1)) 						addr_inc <= 1;		end	end	// shift command in	always @(posedge SCK) begin		// default state: no access		cf_reg  <= 1;		cf_ce   <= 1;		cf_oe   <= 1;					cf_iord <= 1;				cf_iowr <= 1;				cf_we   <= 1;				// latch address register, this is not shifted, since this		// way we won't see glitches e.g. in the reset line built by		// the address register bit 15 during address loads		if(cmd_reg == `SET_ADDR) begin			if(state == 1) address_reg[7-bit_counter]  <= SIN;			if(state == 2) address_reg[15-bit_counter] <= SIN;		end		if((addr_inc) && (bit_counter == 7)) begin			// address register bits 13 and 14 determine the address mode			// and bits 0..10 actually are addresses			case( address_reg[12:11] )				// toggle odd/even byte address				1: address_reg[0] <= !address_reg[0];				// increment byte				2: address_reg[10:0] <= address_reg[10:0] + 1;				// increment word				3: address_reg[10:0] <= address_reg[10:0] + 2;							endcase		end					// permanently shift data in		data_reg = { data_reg[6:0], SIN };
		// and permanently latch the data from the data bus		if(bit_counter == 7)
			data_in_reg <= DATA;
		// command phase: shift three command bits in		if( (state == 0) && (bit_counter < 3) )			cmd_reg <= { cmd_reg[1:0], SIN };		// read is active already in state 1, the data will then be sent via spi		// in the next state		if( cmd_cf_read && (((state == 0)&&(bit_counter == 7)) ||(state >= 1)  )) begin			cf_ce <= 0;			// register select			if(( cmd_reg == `REG_READ ) || (cmd_reg == `IO_READ))	cf_reg <= 0;				// enable read signals			if ( bit_counter < 7) begin				if( cmd_reg == `REG_READ )	cf_oe   <= 0;				if( cmd_reg == `IO_READ )	cf_iord <= 0;			end		end		// write starts in state 2 since its delayed by one after input		if( cmd_cf_write && (((state == 1)&&(bit_counter == 7)) ||(state >= 2)  )) begin			cf_ce <= 0;			// register select			if(( cmd_reg == `REG_WRITE ) || (cmd_reg == `IO_WRITE)) cf_reg <= 0;			// enable write signals			if ( bit_counter < 7) begin				if( cmd_reg == `REG_WRITE && bit_counter < 6) cf_we   <= 0;				if( cmd_reg == `IO_WRITE )  cf_iowr <= 0;			end				end			end	// shift result out on negative edge to have it valid on positive	always @(negedge SCK) begin		// latch data for output		if(bit_counter == 7) begin			data_out_reg <= data_reg;			// these are the only two cases where the out_reg is latched. this			// means that this byte can be returned during a command transfer. this			// is necessary to be able to fetch the last byte in a read phase by			// issuing e.g. the get_id command.			if( cmd_reg == `GET_ID ) begin				if(state[0]) begin					// msb is "card is present" bit					out_reg[7]   <= CD; 					out_reg[6:0] <= `VERSION_HI; 				end 				else					out_reg <= `VERSION_LO; 			end						if( cmd_cf_read )							out_reg <= data_in_reg; 		end		else			out_reg <= { out_reg[6:0], 1'b0 };	end	// internal wires	assign cmd_internal = ((cmd_reg == `GET_ID) || (cmd_reg == `SET_ADDR));	assign cmd_cf_read  = ((cmd_reg == `REG_READ) || (cmd_reg == `MEM_READ) || 									(cmd_reg == `IO_READ));	assign cmd_cf_write = ((cmd_reg == `REG_WRITE) || (cmd_reg == `MEM_WRITE) || 									(cmd_reg == `IO_WRITE));	// drive outputs	assign SOUT = (!SS)?out_reg[7]:1'bz;	assign ADDRESS = address_reg[10:0];   // 12:11 are used internally for auto address	assign LED = address_reg[13];         // 13 is LED output, 14 is unused	assign CFRST = address_reg[15];       // 15 is reset	// drive control signals	assign CE = cf_ce;		assign REG = cf_reg;	assign OE = cf_oe;	assign WE = cf_we;	assign IORD = cf_iord;	assign IOWR = cf_iowr;	assign INT = 1;            // INT isn't used yet, tie to VCC		// drive data lines if a write command is scheduled, if chip is selected and	// if we are in state 2 or 3 (data is being written) and within bits 2 to 7	// (cf card is selected)	assign DATA = (cmd_cf_write && (state >= 2))? data_out_reg : 8'hzz;endmodule

⌨️ 快捷键说明

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