99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Verilog實(shí)現(xiàn)講解

冬至子 ? 來源:Bug記錄 ? 作者:woodfan ? 2023-06-16 09:52 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

verilog第一步肯定需要將輸入輸出端口,常量等信息補(bǔ)齊全;

module spi_ctrl
#(
parameter	SPI_ADDR_WIDTH = 16,
parameter	SPI_CMD_WIDTH  = 24,
parameter	SPI_IDLE = 0
)
(
	/* System signal */
	input					clk			,
	input					rst			,
	
	/* User Data */
	input		[23:0]			cmd_data		,
	output 	reg	[ 7:0]			read_data		,
	input					en			,
	input					ready			,
	output	reg				sink_vld		,
	
	/* SPI interface */
	output	reg			 	spi_clk			,
	output	reg				spi_enb			,
	output	reg				spi_di			,
	input					spi_do
);

設(shè)置SPI_ADDR_WIDTH標(biāo)記SPI傳輸數(shù)據(jù)命令的寄存器地址值寬度,SPI_CMD_WIDTH變量標(biāo)記SPI傳輸數(shù)據(jù)的整體寬度。

輸入輸出變量中,clk時(shí)鐘信號和rst復(fù)位信號都是必備的系統(tǒng)信號;除去SPI接口的4根數(shù)據(jù)線外,還有輸入的24位cmd_data,將需要發(fā)送的數(shù)據(jù)從這個(gè)端口傳遞給SPI處理;輸出的8位read_data,將讀取到的寄存器數(shù)據(jù)輸出便于做后續(xù)處理;以及控制信號,en控制SPI的工作速率,ready指示SPI發(fā)送工作的開始,sink_vld指示SPI發(fā)送讀取工作的結(jié)束。

上一篇文章談到,我們將整個(gè)SPI的發(fā)送讀取分為5個(gè)狀態(tài),

圖片

SPI狀態(tài)機(jī)的5種狀態(tài)

現(xiàn)在我們需要捋順每個(gè)狀態(tài)跳轉(zhuǎn)的條件;IDLE空閑狀態(tài)跳轉(zhuǎn)到WRITE_ADDR寫地址狀態(tài),說明此時(shí)需要發(fā)送SPI數(shù)據(jù),所以ready信號是跳轉(zhuǎn)條件;從上圖可以看到,WRITE_ADDR寫地址狀態(tài)可以跳轉(zhuǎn)到WRITE_DATA狀態(tài)或READ狀態(tài),而決定條件是SPI的命令是讀取命令還是寫入命令,這取決于SPI寫入數(shù)據(jù)的MSB(最高位);WRITE_DATA狀態(tài)和READ狀態(tài)跳轉(zhuǎn)回IDLE空閑狀態(tài)的條件是需要發(fā)送的數(shù)據(jù)已經(jīng)發(fā)送完畢或需要讀取的數(shù)據(jù)已經(jīng)讀取完畢。

另外,在WRITE_ADDR寫地址狀態(tài),WRITE_DATA狀態(tài)和READ狀態(tài)里面需要用到計(jì)數(shù)器,記錄當(dāng)前已經(jīng)發(fā)送或讀取的數(shù)據(jù)量,作為跳出該狀態(tài)的判斷依據(jù)之一。

由于這部分的狀態(tài)機(jī)比較簡單,所以第一版我采用了一段式狀態(tài)機(jī)。為了便于理解SPI_CLK的產(chǎn)生,我選擇使用分頻操作生成SPI_CLK,但其實(shí)更推薦的方式是使用MMCM,PLL等方式產(chǎn)生SPI_CLK。

localparam	SPI_DATA_WIDTH  = SPI_CMD_WIDTH - SPI_ADDR_WIDTH;

assign  flag_write_addr_update = (cnt < SPI_ADDR_WIDTH && spi_clk == 1'b0) ? 1'b1 : 1'b0; 

assign	flag_write_addr_hold = (cnt < SPI_ADDR_WIDTH) ? 1'b1 : 1'b0 ;

assign	flag_data_update = (cnt < SPI_DATA_WIDTH && spi_clk == 1'b0) ? 1'b1 : 1'b0 ;

assign	flag_data_hold = (cnt < SPI_DATA_WIDTH) ? 1'b1 : 1'b0 ;

always @ (posedge clk or posedge rst)
begin
	if (rst)
	begin
		spi_clk		<=	SPI_IDLE	;
		spi_enb		<=	1'b1		;
		spi_di		<=	1'b0		;
		read_data	<=	'd0			;
		sink_vld	<=	1'b0		;
		state		<=	IDLE		;
		cmd_data_r	<=	'd0			;
		cnt			<=	'd0			;
		flag_read	<=	1'b0		;
	end
	else if (en)
	begin
		case (state)
		IDLE:
		begin
			if (ready)
			begin
				state		<= WRITE_ADDR		;
				spi_enb		<=	1'b0		;
				cmd_data_r	<=cmd_data		;
				cnt		<=	'd0		;
				flag_read 	<= !cmd_data[23]	;
			end
			sink_vld 	<=	1'b0;
			spi_di		<=	1'b0;
			spi_enb		<=	1'b1;
		end
		
		WRITE_ADDR:
		begin	
			spi_enb		<=	1'b0;
			if (flag_write_addr_update)
			begin
				spi_di		<=	cmd_data_r[23]			;
				cmd_data_r	<=	{cmd_data_r[22:0], 1'b0}	;
				spi_clk		<=	1'b1				;
				cnt			<=	cnt + 8'd1		;
			end	
			else if (flag_write_addr_hold)
			begin
				spi_clk	<=	1'b0;
			end
			else 
			begin
				if (flag_read)
					state	<=	READ		;
				else
					state	<=	WRITE_DATA	;
				cnt		<=	'd0		;
				spi_clk	<=	1'b0			;
			end
		end
		
		WRITE_DATA:
		begin
			if (flag_data_update)
			begin
				spi_di		<=	cmd_data_r[23]			;
				cmd_data_r	<=	{cmd_data_r[22:0], 1'b0}	;
				spi_clk		<=	1'b1				;
				cnt		<=	cnt + 8'd1			;
			end	
			else if (flag_data_hold)
			begin
				spi_clk		<=	1'b0	;
			end
			else 
			begin
				state 	<= 	IDLE	;
				spi_clk <=	1'b0	;
				sink_vld<=  	1'b1    ;
			end
		end
		
		READ:
		begin
			if (flag_data_update)
			begin
				spi_clk	<=	1'b1	;
			end	
			else if (flag_data_hold)
			begin
				spi_clk		<=	1'b0			;
				read_data[0]	<=	spi_do			;
				read_data[7:1]	<=	read_data[6:0]		;
				cnt		<=	cnt + 8'd1		;
			end
			else 
			begin
				state 		<= IDLE;
				sink_vld 	<= 1'b1;
			end
		end
		default : state <= IDLE;
		endcase
	end
end

從上一個(gè)文章里面,我們可以看到,在WRITE_ADDR寫地址狀態(tài),WRITE_DATA狀態(tài)里,我們需要在SPI_CLK時(shí)鐘的上升沿更新SPI_DO值,在SPI_CLK下降沿保持SPI_DO值;

所以我們需要判斷,

  1. 當(dāng)SPI_CLK為低電平并且傳輸還沒有結(jié)束時(shí),我們需要將SPI_CLK拉高,將需要的發(fā)送數(shù)據(jù)串行數(shù)據(jù)更新到SPI_DI,更新計(jì)數(shù)器值;
  2. 而當(dāng)SPI_CLK為高電平并且傳輸還沒有結(jié)束時(shí),我們僅需要將SPI_CLK拉低,保持SPI_DI不變。

READ狀態(tài)里,我們僅需要在SPI_CLK時(shí)鐘的下降沿采樣SPI_DO值;即

  1. 當(dāng)SPI_CLK為高電平并且傳輸還沒有結(jié)束時(shí),我們需要將SPI_CLK拉低,將SPI_DO采樣并保存至read_data,更新計(jì)數(shù)器值;
  2. 而當(dāng)SPI_CLK為低電平并且傳輸還沒有結(jié)束時(shí),我們僅需要將SPI_CLK拉高。整個(gè)電路的流程就已經(jīng)被我們用verilog描述出來了。

使用VCS仿真之后的結(jié)果,可以見下圖:

圖片

希望通過這一版簡單的講解,能讓大家對SPI的verilog描述有更加清晰的認(rèn)識。

這一版本的SPI最終上板測試沒有問題,但確實(shí)還存在一些問題,不推薦使用生成時(shí)鐘做SPI_CLK, 如果還有更好的建議可以提出來一起討論。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5435

    瀏覽量

    124607
  • VCS
    VCS
    +關(guān)注

    關(guān)注

    0

    文章

    80

    瀏覽量

    9933
  • 狀態(tài)機(jī)
    +關(guān)注

    關(guān)注

    2

    文章

    493

    瀏覽量

    28265
  • CLK
    CLK
    +關(guān)注

    關(guān)注

    0

    文章

    128

    瀏覽量

    17618
  • Verilog語言
    +關(guān)注

    關(guān)注

    0

    文章

    113

    瀏覽量

    8561
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    Verilog語言練習(xí)與講解

    Verilog語言練習(xí)與講解
    發(fā)表于 08-15 16:39

    Verilog語言練習(xí)與講解

    Verilog語言練習(xí)與講解
    發(fā)表于 03-07 13:32

    VHDL 和verilog HDL講解

    VHDL 和verilog HDL講解
    發(fā)表于 10-09 20:32

    Verilog語法基礎(chǔ)講解之參數(shù)化設(shè)計(jì)

    本帖最后由 lee_st 于 2017-10-31 08:46 編輯 Verilog語法基礎(chǔ)講解之參數(shù)化設(shè)計(jì)
    發(fā)表于 10-21 20:56

    Verilog實(shí)現(xiàn)8255芯片功能

    Verilog實(shí)現(xiàn)8255芯片功能
    發(fā)表于 11-03 17:06 ?144次下載

    夏宇聞-verilog經(jīng)典教材

    verilog語言經(jīng)典教材,本書講解verilog的基本語法和經(jīng)典例子等等。
    發(fā)表于 11-10 11:44 ?24次下載

    數(shù)字系統(tǒng)設(shè)計(jì):VERILOG實(shí)現(xiàn)

    數(shù)字系統(tǒng)設(shè)計(jì):VERILOG實(shí)現(xiàn) (第2版)
    發(fā)表于 11-30 10:21 ?0次下載

    verilog_實(shí)現(xiàn)_LCD顯示

    關(guān)于fpga和LCD方面的知識,verilog實(shí)現(xiàn)的LCD顯示的設(shè)計(jì)
    發(fā)表于 05-16 18:04 ?47次下載

    Verilog語言練習(xí)與講解2

    Verilog語言練習(xí)與講解2,感興趣的小伙伴們可以瞧一瞧。
    發(fā)表于 11-10 15:29 ?1次下載

    Verilog語言練習(xí)與講解1

    Verilog語言練習(xí)與講解1,感興趣的小伙伴們可以瞧一瞧。
    發(fā)表于 11-10 15:29 ?2次下載

    Verilog實(shí)現(xiàn)74LS194芯片設(shè)計(jì)程序

    Verilog作為一種種硬件描述語言目前已經(jīng)得到了普遍運(yùn)用。本文主要介紹了Verilog特點(diǎn)、Verilog用途以及Verilog實(shí)現(xiàn)74L
    發(fā)表于 12-22 17:26 ?7058次閱讀

    FPGA verilog相關(guān)視頻:quartus中的qsys的講解

    該課程是正點(diǎn)原子團(tuán)隊(duì)編寫,詳細(xì)講解了quartus中的qsys。也可以從我頭像點(diǎn)進(jìn)去看FPGA verilog相關(guān)的視頻。
    的頭像 發(fā)表于 08-06 06:02 ?3401次閱讀
    FPGA <b class='flag-5'>verilog</b>相關(guān)視頻:quartus中的qsys的<b class='flag-5'>講解</b>

    FPGA設(shè)計(jì)中DAC控制的Verilog實(shí)現(xiàn)圖文稿

    FPGA設(shè)計(jì)中DAC控制的Verilog實(shí)現(xiàn)圖文稿(ltspice 放置電源)-該文檔為FPGA設(shè)計(jì)中DAC控制的Verilog實(shí)現(xiàn)圖文稿資料,講解
    發(fā)表于 07-26 12:17 ?10次下載
    FPGA設(shè)計(jì)中DAC控制的<b class='flag-5'>Verilog</b><b class='flag-5'>實(shí)現(xiàn)</b>圖文稿

    FPGA設(shè)計(jì)中DAC控制的Verilog實(shí)現(xiàn)

    FPGA設(shè)計(jì)中DAC控制的Verilog實(shí)現(xiàn)(單片機(jī)電源維修)-該文檔為FPGA設(shè)計(jì)中DAC控制的Verilog實(shí)現(xiàn)資料,講解的還不錯,感興
    發(fā)表于 07-26 12:18 ?18次下載
    FPGA設(shè)計(jì)中DAC控制的<b class='flag-5'>Verilog</b><b class='flag-5'>實(shí)現(xiàn)</b>

    FPGA設(shè)計(jì)中DAC控制的Verilog實(shí)現(xiàn)修訂稿

    FPGA設(shè)計(jì)中DAC控制的Verilog實(shí)現(xiàn)修訂稿(空調(diào)電源芯片)-該文檔為FPGA設(shè)計(jì)中DAC控制的Verilog實(shí)現(xiàn)修訂稿資料,講解的還
    發(fā)表于 07-26 13:13 ?10次下載
    FPGA設(shè)計(jì)中DAC控制的<b class='flag-5'>Verilog</b><b class='flag-5'>實(shí)現(xiàn)</b>修訂稿