首页
游戏
影视
直播
广播
听书
音乐
图片
更多
看书
微视
主播
统计
友链
留言
关于
论坛
邮件
推荐
我的硬盘
我的搜索
我的记录
我的文件
我的图书
我的笔记
我的书签
我的微博
Search
1
在IC617中进行xa+vcs数模混仿
81 阅读
2
科普:Memory Compiler生成的Register file和SRAM有何区别?
73 阅读
3
virtuoso和empyrean alps模拟仿真和混仿教程
73 阅读
4
后仿中$setup,$hold与$setuphold
44 阅读
5
文档内容搜索哪家强? 15款文件搜索软件横向评测
35 阅读
默认分类
芯片市场
数字电路
芯片后端
模拟电路
芯片验证
原型与样片验证
算法与架构
DFX与量产封装
PC&Server OS设置
移动OS设置
软件方案
新浪备份
有道备份
登录
Search
标签搜索
python
Docker
vscode
linux
systemverilog
vcs
STM32
PyQT
EDA
FPGA
gvim
cadence
Alist
xilinx
UVM
uos
macos
package
MCU
risc-v
bennyhe
累计撰写
378
篇文章
累计收到
31
条评论
首页
栏目
默认分类
芯片市场
数字电路
芯片后端
模拟电路
芯片验证
原型与样片验证
算法与架构
DFX与量产封装
PC&Server OS设置
移动OS设置
软件方案
新浪备份
有道备份
页面
游戏
影视
直播
广播
听书
音乐
图片
看书
微视
主播
统计
友链
留言
关于
论坛
邮件
推荐
我的硬盘
我的搜索
我的记录
我的文件
我的图书
我的笔记
我的书签
我的微博
搜索到
1
篇与
的结果
2026-01-06
spi master接口的fpga实现
https://www.cnblogs.com/kingstacker/p/7490002.html前言当你器件的引脚贼少的时候,需要主机和从机通信,spi就派上了用场,它可以一对多,但只是片选到的从机能和主机通信,其他的挂机。spi:serial peripheral interface 串行外围接口大致了解:spi是个同步协议,数据在master和slaver间交换通过时钟sck,由于它是同步协议,时钟速率就可以各种变换。sck:主机提供,从机不能操控,从器件由主机产生的时钟控制。数据只有在sck来了的上升沿或者下降沿才传输。高级一点的spi芯片有配置寄存器,高级一点的工作有四种模式,采样相位和sck空闲电平可配置。当然在这里我们主要实现简单的spi协议:sck是系统时钟的四分频,wr请求信号有效时,主机开始工作,数据位8bit,sck空闲时低电平,工作时第一个沿数据传输。只有一个从机,cs低电平片选。看下结构:接口定义:编码实现:(版权所有,请勿用于商业用途,仅供学习使用)//************************************************ // Filename : spi_ms_test1.v // Author : Kingstacker // Company : School // Email : kingstacker_work@163.com // Device : Altera cyclone4 ep4ce6f17c8 // Description : spi master module;data 8bit;sck is 4 div of the clk; //************************************************ module spi_ms #(parameter WIDTH = 8)( //input; input wire clk, input wire rst_n, input wire wr, //send request; input wire [WIDTH-1:0] master_din, //the data you want send; input wire miso, //the data form slave; //output; output reg cs, //slave select; output reg sck, //data exchange clock; output reg mosi, //master out; output reg [WIDTH-1:0] master_dout //the data you received; ); localparam CLK_HZ = 50_000_000; //clk frequency; localparam SCK_HZ = 12_500_000; //sck frequency; localparam DIV_NUMBER = CLK_HZ / SCK_HZ; localparam CNT_MAX = (DIV_NUMBER >>1) - 1'b1; localparam DATA_CNT_MAX = 5'd31; localparam MOSI_CNT_MAX = 3'd7; localparam IDEL = 2'b00; localparam SEND = 2'b01; localparam FINISH = 2'b10; reg cnt; //sck cnt; reg sck_en; //enable sck; reg data_cnt_en; reg sck_reg1; reg sck_reg2; wire sck_p; //posedge sck; wire sck_n; //negedge sck; wire send_over; reg [1:0] cstate; reg [4:0] data_cnt; //cnt the send data; reg [2:0] mosi_cnt; reg [WIDTH-1:0] master_din_reg; reg [WIDTH-1:0] master_dout_reg; //produce sck; always @(posedge clk or negedge rst_n) begin if (~rst_n) begin cnt <= 0; sck <= 1'b0; end //if else begin if (sck_en == 1'b1) begin if (cnt == CNT_MAX) begin cnt <= 0; sck <= ~sck; end else begin cnt <= cnt + 1'b1; sck <= sck; end end else begin cnt <= 0; sck <= 1'b0; end end //else end //always //produce sck_p and sck_n; always @(posedge clk or negedge rst_n) begin if (~rst_n) begin sck_reg1 <= 1'b0; sck_reg2 <= 1'b0; end //if else begin sck_reg1 <= sck; sck_reg2 <= sck_reg1; end //else end //always assign sck_p = (sck_reg1 & (~sck_reg2)); //sck posedge; assign sck_n = ((~sck_reg1) & sck_reg2); //sck negedge; //fsm;hot code; always @(posedge clk or negedge rst_n) begin if (~rst_n) begin cstate <= IDEL; end else begin case (cstate) IDEL: cstate <= (wr)? SEND : IDEL; SEND: cstate <= (send_over) ? FINISH : SEND; FINISH: cstate <= IDEL; default: cstate <= IDEL; endcase //case end end always @(posedge clk or negedge rst_n) begin if (~rst_n) begin cs <= 1'b1; data_cnt_en <= 1'b0; sck_en <= 1'b0; master_din_reg <= 0; master_dout <= 0; end else begin case (cstate) IDEL: begin data_cnt_en <= 1'b0; master_din_reg <= (wr) ? master_din : master_din_reg; //load the data you want send to slaver; end SEND: begin data_cnt_en <= 1'b1; cs <= 1'b0; sck_en <= 1'b1; master_dout <= (send_over) ? master_dout_reg : master_dout; //master receiverd data; end FINISH: begin //send and load ok; sck_en <= 1'b0; cs <= 1'b1; data_cnt_en <= 1'b0; end default: begin cs <= 1'b1; sck_en <= 1'b0; data_cnt_en <= 1'b0; end endcase //case end end always @(posedge clk or negedge rst_n) begin if (~rst_n) begin data_cnt <= 0; end else begin data_cnt <= (data_cnt_en) ? (data_cnt + 1'b1) : 5'd0; //4 div * 8bit = 32 cnt; end end assign send_over = (data_cnt == DATA_CNT_MAX) ? 1'b1 : 1'b0; //rising edge miso; always @(posedge clk or negedge rst_n) begin if (~rst_n) begin master_dout_reg <= 0; end else begin master_dout_reg <= (sck_p) ? {master_dout_reg[6:0],miso} : master_dout_reg; end end //mosi; always @(posedge clk or negedge rst_n) begin if (~rst_n) begin mosi_cnt <= 0; end else begin if (sck_n) begin if (mosi_cnt == MOSI_CNT_MAX) begin mosi_cnt <= 0; end else begin mosi_cnt <= mosi_cnt + 1'b1; end end else begin mosi_cnt <= mosi_cnt; end end end always @(posedge clk or negedge rst_n) begin if (~rst_n) begin mosi <= 1'b0; end else begin mosi <= (sck_n) ? master_din_reg[MOSI_CNT_MAX-mosi_cnt] : mosi; end end endmodule仿真:综合资源使用:Fmax:
2026年01月06日
1 阅读
0 评论
0 点赞