0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Verilog实现讲解

冬至子 来源:Bug记录 作者:woodfan 2023-06-16 09:52 次阅读

verilog第一步肯定需要将输入输出端口,常量等信息补齐全;

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
);

设置SPI_ADDR_WIDTH标记SPI传输数据命令的寄存器地址值宽度,SPI_CMD_WIDTH变量标记SPI传输数据的整体宽度。

输入输出变量中,clk时钟信号和rst复位信号都是必备的系统信号;除去SPI接口的4根数据线外,还有输入的24位cmd_data,将需要发送的数据从这个端口传递给SPI处理;输出的8位read_data,将读取到的寄存器数据输出便于做后续处理;以及控制信号,en控制SPI的工作速率,ready指示SPI发送工作的开始,sink_vld指示SPI发送读取工作的结束。

上一篇文章谈到,我们将整个SPI的发送读取分为5个状态,

图片

SPI状态机的5种状态

现在我们需要捋顺每个状态跳转的条件;IDLE空闲状态跳转到WRITE_ADDR写地址状态,说明此时需要发送SPI数据,所以ready信号是跳转条件;从上图可以看到,WRITE_ADDR写地址状态可以跳转到WRITE_DATA状态或READ状态,而决定条件是SPI的命令是读取命令还是写入命令,这取决于SPI写入数据的MSB(最高位);WRITE_DATA状态和READ状态跳转回IDLE空闲状态的条件是需要发送的数据已经发送完毕或需要读取的数据已经读取完毕。

另外,在WRITE_ADDR写地址状态,WRITE_DATA状态和READ状态里面需要用到计数器,记录当前已经发送或读取的数据量,作为跳出该状态的判断依据之一。

由于这部分的状态机比较简单,所以第一版我采用了一段式状态机。为了便于理解SPI_CLK的产生,我选择使用分频操作生成SPI_CLK,但其实更推荐的方式是使用MMCM,PLL等方式产生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

从上一个文章里面,我们可以看到,在WRITE_ADDR写地址状态,WRITE_DATA状态里,我们需要在SPI_CLK时钟的上升沿更新SPI_DO值,在SPI_CLK下降沿保持SPI_DO值;

所以我们需要判断,

  1. 当SPI_CLK为低电平并且传输还没有结束时,我们需要将SPI_CLK拉高,将需要的发送数据串行数据更新到SPI_DI,更新计数器值;
  2. 而当SPI_CLK为高电平并且传输还没有结束时,我们仅需要将SPI_CLK拉低,保持SPI_DI不变。

READ状态里,我们仅需要在SPI_CLK时钟的下降沿采样SPI_DO值;即

  1. 当SPI_CLK为高电平并且传输还没有结束时,我们需要将SPI_CLK拉低,将SPI_DO采样并保存至read_data,更新计数器值;
  2. 而当SPI_CLK为低电平并且传输还没有结束时,我们仅需要将SPI_CLK拉高。整个电路的流程就已经被我们用verilog描述出来了。

使用VCS仿真之后的结果,可以见下图:

图片

希望通过这一版简单的讲解,能让大家对SPI的verilog描述有更加清晰的认识。

这一版本的SPI最终上板测试没有问题,但确实还存在一些问题,不推荐使用生成时钟做SPI_CLK, 如果还有更好的建议可以提出来一起讨论。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5258

    浏览量

    119422
  • VCS
    VCS
    +关注

    关注

    0

    文章

    78

    浏览量

    9544
  • 状态机
    +关注

    关注

    2

    文章

    489

    浏览量

    27412
  • CLK
    CLK
    +关注

    关注

    0

    文章

    126

    浏览量

    17070
  • Verilog语言
    +关注

    关注

    0

    文章

    113

    浏览量

    8192
收藏 人收藏

    评论

    相关推荐

    Verilog语言练习与讲解

    Verilog语言练习与讲解
    发表于 08-15 16:39

    Verilog语言练习与讲解

    Verilog语言练习与讲解
    发表于 03-07 13:32

    VHDL 和verilog HDL讲解

    VHDL 和verilog HDL讲解
    发表于 10-09 20:32

    Verilog语法基础讲解之参数化设计

    本帖最后由 lee_st 于 2017-10-31 08:46 编辑 Verilog语法基础讲解之参数化设计
    发表于 10-21 20:56

    Verilog实现8255芯片功能

    Verilog实现8255芯片功能
    发表于 11-03 17:06 144次下载

    夏宇闻-verilog经典教材

    verilog语言经典教材,本书讲解verilog的基本语法和经典例子等等。
    发表于 11-10 11:44 23次下载

    数字系统设计:VERILOG实现

    数字系统设计:VERILOG实现 (第2版)
    发表于 11-30 10:21 0次下载

    verilog_实现_LCD显示

    关于fpga和LCD方面的知识,verilog实现的LCD显示的设计
    发表于 05-16 18:04 47次下载

    Verilog语言练习与讲解2

    Verilog语言练习与讲解2,感兴趣的小伙伴们可以瞧一瞧。
    发表于 11-10 15:29 1次下载

    Verilog语言练习与讲解1

    Verilog语言练习与讲解1,感兴趣的小伙伴们可以瞧一瞧。
    发表于 11-10 15:29 2次下载

    Verilog实现74LS194芯片设计程序

    Verilog作为一种种硬件描述语言目前已经得到了普遍运用。本文主要介绍了Verilog特点、Verilog用途以及Verilog实现74L
    发表于 12-22 17:26 6562次阅读

    FPGA verilog相关视频:quartus中的qsys的讲解

    该课程是正点原子团队编写,详细讲解了quartus中的qsys。也可以从我头像点进去看FPGA verilog相关的视频。
    的头像 发表于 08-06 06:02 2985次阅读
    FPGA <b class='flag-5'>verilog</b>相关视频:quartus中的qsys的<b class='flag-5'>讲解</b>

    FPGA设计中DAC控制的Verilog实现图文稿

    FPGA设计中DAC控制的Verilog实现图文稿(ltspice 放置电源)-该文档为FPGA设计中DAC控制的Verilog实现图文稿资料,讲解
    发表于 07-26 12:17 10次下载
    FPGA设计中DAC控制的<b class='flag-5'>Verilog</b><b class='flag-5'>实现</b>图文稿

    FPGA设计中DAC控制的Verilog实现

    FPGA设计中DAC控制的Verilog实现(单片机电源维修)-该文档为FPGA设计中DAC控制的Verilog实现资料,讲解的还不错,感兴
    发表于 07-26 12:18 18次下载
    FPGA设计中DAC控制的<b class='flag-5'>Verilog</b><b class='flag-5'>实现</b>

    FPGA设计中DAC控制的Verilog实现修订稿

    FPGA设计中DAC控制的Verilog实现修订稿(空调电源芯片)-该文档为FPGA设计中DAC控制的Verilog实现修订稿资料,讲解的还
    发表于 07-26 13:13 10次下载
    FPGA设计中DAC控制的<b class='flag-5'>Verilog</b><b class='flag-5'>实现</b>修订稿