当前位置: 首页 > wzjs >正文

河南app软件开发合肥seo优化排名公司

河南app软件开发,合肥seo优化排名公司,靠谱的网站建设公司,青岛专业网站排名推广1. 驱动的作用 调用SPI底层驱动,实现DS1302的驱动 2. 关键程序代码说明 1. 独热编码设置状态机的状态 使用独热编码会使系统更加高效稳定 localparam IDLE 8b0000_0001; localparam CE_HIGH 8b0000_0010; localparam CE_LOW 8b0000_0100; localparam…

1. 驱动的作用

调用SPI底层驱动,实现DS1302的驱动

2. 关键程序代码说明

1. 独热编码设置状态机的状态

使用独热编码会使系统更加高效稳定

localparam IDLE     = 8'b0000_0001;
localparam CE_HIGH  = 8'b0000_0010;
localparam CE_LOW   = 8'b0000_0100;
localparam WR_ADDR  = 8'b0000_1000;
localparam WR_DATA  = 8'b0001_0000;
localparam RD_ADDR  = 8'b0010_0000;
localparam RD_DATA  = 8'b0100_0000;
localparam ACK      = 8'b1000_0000;
2. 状态跳转条件的设置
wire IDLE_CE_HIGH    = (cstate == IDLE)         && (cmd_read || cmd_write)  ;
wire CE_HIGH_WR_ADDR = (cstate == CE_HIGH)      && end_cnt_num   && cmd_write           ;
wire WR_ADDR_WR_DATA = (cstate == WR_ADDR)      && wr_ack                   ;
wire WR_DATA_CE_LOW  = (cstate == WR_DATA)      && wr_ack                   ;
wire CE_LOW_ACK      = (cstate == CE_LOW)       && end_cnt_num              ;
wire ACK_IDLE        = (cstate == ACK)          && end_cnt_num              ;wire CE_HIGH_RD_ADDR = (cstate == CE_HIGH)      && end_cnt_num   &&  cmd_read          ;
wire RD_ADDR_RD_DATA = (cstate == RD_ADDR)      && wr_ack                   ;
wire RD_DATA_CE_LOW  = (cstate == RD_DATA)      && wr_ack                   ;
3. end_cnt_num的使用说明

end_cnt_numcnt_clk开始计数并且计数到最大值的时候拉高一个clk节拍,此时由于end_cnt_num的拉高的一个节拍会使cnt_num的值加一(整个过程比较复杂,这里一笔带过,需要仔细了解的朋友可以拿代码去仿真)

4. 二段式状态机

两段式状态机比较推荐,拥有更高的执行效率和稳定性,推荐使用,特别注意一点,组合逻辑使用阻塞赋值,所有的else条件必须写,否则可能会引起latch

always @(posedge clk or posedge rst) beginif(rst)begincstate <= IDLE;end else begincstate <= nstate;end
endalways @(*) begincase (cstate)IDLE     :if(IDLE_CE_HIGH)nstate = CE_HIGH;elsenstate = cstate;CE_HIGH  :if(CE_HIGH_RD_ADDR)nstate = RD_ADDR;else if(CE_HIGH_WR_ADDR)nstate = WR_ADDR;elsenstate = cstate;CE_LOW   :if(CE_LOW_ACK)nstate = ACK;elsenstate = cstate;WR_ADDR  :if(WR_ADDR_WR_DATA)nstate = WR_DATA;elsenstate = cstate;WR_DATA  :if(WR_DATA_CE_LOW)nstate = CE_LOW;elsenstate = cstate;RD_ADDR  :if(RD_ADDR_RD_DATA)nstate = RD_DATA;elsenstate = cstate;RD_DATA  :if(RD_DATA_CE_LOW)nstate = CE_LOW;elsenstate = cstate;ACK      :if(ACK_IDLE)nstate = IDLE;elsenstate = cstate;default  :nstate = IDLE;endcase
end
5. 数据的收发部分

注意这里面有数据字节的对应问题,SPI收发数据都是从低位开始,也就是LSB,需要把用户的传入的数据或者用户需要读出的数据进行位置变换,具体实现如下

always @(posedge clk or posedge rst) beginif(rst)beginsend_data <= 8'd0;end else if(cstate == WR_ADDR)beginsend_data <= {1'b0, write_addr[1],write_addr[2],write_addr[3],write_addr[4],write_addr[5],write_addr[6],1'b1};end else if(cstate == RD_ADDR)beginsend_data <= {1'b1, read_addr[1],read_addr[2],read_addr[3],read_addr[4],read_addr[5],read_addr[6],1'b1};end else if(cstate == WR_DATA)beginsend_data <= {write_data[0],write_data[1],write_data[2],write_data[3],write_data[4],write_data[5],write_data[6],write_data[7]};end
endalways @(posedge clk or posedge rst) beginif(rst)beginread_data <= 8'd0;end else if(cstate == RD_DATA_CE_LOW)beginread_data <= {data_rec[0],data_rec[1],data_rec[2],data_rec[3],data_rec[4],data_rec[5],data_rec[6],data_rec[7]};end else beginread_data <= 8'd0;end
end

3. 仿真验证

1. 写过程

在这里插入图片描述

2. 读过程

在这里插入图片描述

4. 完整代码

module ds1302_io1(input                               clk                        ,input                               rst                        ,output                              ds1302_ce                  ,// 1output                              ds1302_sclk                ,// 1inout                               ds1302_io                  ,input                               cmd_read                   ,input                               cmd_write                  ,output                              cmd_write_ack              ,// 1output                              cmd_read_ack               ,// 1 input              [   7:0]         write_addr                 ,input              [   7:0]         read_addr                  ,input              [   7:0]         write_data                 ,output reg         [   7:0]         read_data                   //1
);localparam IDLE     = 8'b0000_0001;
localparam CE_HIGH  = 8'b0000_0010;
localparam CE_LOW   = 8'b0000_0100;
localparam WR_ADDR  = 8'b0000_1000;
localparam WR_DATA  = 8'b0001_0000;
localparam RD_ADDR  = 8'b0010_0000;
localparam RD_DATA  = 8'b0100_0000;
localparam ACK      = 8'b1000_0000;wire [25:0]MAX_CNT = 256;
reg [7:0]cstate;
reg [7:0]nstate;
reg [3:0]num;
reg [8:0]cnt_clk;
reg [3:0]cnt_num;
reg CS_reg;
wire add_cnt_clk = cstate != IDLE;
wire end_cnt_clk = add_cnt_clk && cnt_clk == MAX_CNT - 1;
wire add_cnt_num = end_cnt_clk;
wire end_cnt_num = add_cnt_num && cnt_num == num - 1;
wire wr_ack;reg [7:0]send_data ;
wire [7:0]data_rec  ;
wire IDLE_CE_HIGH    = (cstate == IDLE)         && (cmd_read || cmd_write)  ;
wire CE_HIGH_WR_ADDR = (cstate == CE_HIGH)      && end_cnt_num   && cmd_write           ;
wire WR_ADDR_WR_DATA = (cstate == WR_ADDR)      && wr_ack                   ;
wire WR_DATA_CE_LOW  = (cstate == WR_DATA)      && wr_ack                   ;
wire CE_LOW_ACK      = (cstate == CE_LOW)       && end_cnt_num              ;
wire ACK_IDLE        = (cstate == ACK)          && end_cnt_num              ;wire CE_HIGH_RD_ADDR = (cstate == CE_HIGH)      && end_cnt_num   &&  cmd_read          ;
wire RD_ADDR_RD_DATA = (cstate == RD_ADDR)      && wr_ack                   ;
wire RD_DATA_CE_LOW  = (cstate == RD_DATA)      && wr_ack                   ;
assign cmd_write_ack  = WR_DATA_CE_LOW;
assign cmd_read_ack   = RD_DATA_CE_LOW;
// wire CS_reg = cstate == ;//
always @(posedge clk or posedge rst) beginif(rst)beginCS_reg <= 1'b0;end else if(IDLE_CE_HIGH)beginCS_reg <= 1'b1;end else if(WR_DATA_CE_LOW || RD_DATA_CE_LOW)beginCS_reg <= 1'b1;   end
endreg [8*20-1:0]state_name;
always @(*) begincase (cstate)
IDLE     :begin num = 1;state_name = "IDLE   "; end
CE_HIGH  :begin num = 1;state_name = "CE_HIGH"; end
CE_LOW   :begin num = 1;state_name = "CE_LOW "; end
WR_ADDR  :begin num = 1;state_name = "WR_ADDR"; end
WR_DATA  :begin num = 1;state_name = "WR_DATA"; end
RD_ADDR  :begin num = 1;state_name = "RD_ADDR"; end
RD_DATA  :begin num = 1;state_name = "RD_DATA"; end
ACK      :begin num = 1;state_name = "ACK    "; end
default  :begin num = 1;state_name = "IDLE   "; end  endcase
endalways @(posedge clk or posedge rst) beginif(rst)begincnt_clk <= 9'd0;end else if(add_cnt_clk)beginif(end_cnt_clk)cnt_clk <= 9'd0;elsecnt_clk <= cnt_clk + 9'd1;end
end
always @(posedge clk or posedge rst) beginif(rst)begincnt_num <= 4'd0;end else if(add_cnt_num)beginif(end_cnt_num)cnt_num <= 4'd0;elsecnt_num <= cnt_num + 4'd1;end
endalways @(posedge clk or posedge rst) beginif(rst)begincstate <= IDLE;end else begincstate <= nstate;end
endalways @(*) begincase (cstate)IDLE     :if(IDLE_CE_HIGH)nstate = CE_HIGH;elsenstate = cstate;CE_HIGH  :if(CE_HIGH_RD_ADDR)nstate = RD_ADDR;else if(CE_HIGH_WR_ADDR)nstate = WR_ADDR;elsenstate = cstate;CE_LOW   :if(CE_LOW_ACK)nstate = ACK;elsenstate = cstate;WR_ADDR  :if(WR_ADDR_WR_DATA)nstate = WR_DATA;elsenstate = cstate;WR_DATA  :if(WR_DATA_CE_LOW)nstate = CE_LOW;elsenstate = cstate;RD_ADDR  :if(RD_ADDR_RD_DATA)nstate = RD_DATA;elsenstate = cstate;RD_DATA  :if(RD_DATA_CE_LOW)nstate = CE_LOW;elsenstate = cstate;ACK      :if(ACK_IDLE)nstate = IDLE;elsenstate = cstate;default  :nstate = IDLE;endcase
endassign wr_req = cstate == RD_ADDR || cstate == WR_ADDR|| cstate == WR_DATA || cstate == RD_DATA;//读数据也要写请求吗   是的  代表启动SPI总线always @(posedge clk or posedge rst) beginif(rst)beginsend_data <= 8'd0;end else if(cstate == WR_ADDR)beginsend_data <= {1'b0, write_addr[1],write_addr[2],write_addr[3],write_addr[4],write_addr[5],write_addr[6],1'b1};end else if(cstate == RD_ADDR)beginsend_data <= {1'b1, read_addr[1],read_addr[2],read_addr[3],read_addr[4],read_addr[5],read_addr[6],1'b1};end else if(cstate == WR_DATA)beginsend_data <= {write_data[0],write_data[1],write_data[2],write_data[3],write_data[4],write_data[5],write_data[6],write_data[7]};end
endalways @(posedge clk or posedge rst) beginif(rst)beginread_data <= 8'd0;end else if(cstate == RD_DATA_CE_LOW)beginread_data <= {data_rec[0],data_rec[1],data_rec[2],data_rec[3],data_rec[4],data_rec[5],data_rec[6],data_rec[7]};end else beginread_data <= 8'd0;end
endspi_master spi_master_m0(.clk                               (clk                       ),.rst                               (rst                       ),.nCS                               (ds1302_ce                 ),.DCLK                              (ds1302_sclk               ),//.MOSI                              (MOSI                      ),.MISO                              (MISO                      ),.CPOL                              (1'b0                      ),.CPHA                              (1'b0                      ),.nCS_ctrl                          (CS_reg                    ),.clk_div                           (16'd50                    ),.wr_req                            (wr_req                    ),.wr_ack                            (wr_ack                    ),.data_in                           (send_data                 ),.data_out                          (data_rec                  ) 
);endmodule
http://www.dtcms.com/wzjs/23179.html

相关文章:

  • 杭州制作网站公司如何给公司做网络推广
  • 东莞网站建设做网站人工智能培训机构
  • 网站移动端怎么做项目网站
  • 上海哪家公司做网站最好网址大全实用网址
  • 前端做项目网站引流最好的推广方法
  • 网站教学推广找客户平台
  • 网络公司网站开发案例深圳网络营销运营
  • 律师做网站推广有用吗哪里有学计算机培训班
  • 国外什么网站是做外贸深圳外包网络推广
  • 服装培训网站建设搜索量排行
  • 成人用品怎样做网站推广山东最新消息今天
  • 网页设计效果图分析西安seo顾问培训
  • 网站地址怎么做超链接搜索引擎优化通常要注意的问题有
  • 本网站只做信息展示不提供在线交易做网站的网络公司
  • 天天斗地主官方网站开发网络营销人员招聘
  • 成都科技网站建设热优化推广服务
  • 城市建设网站金郑州seo推广优化
  • phpcms 手机网站如何自己编写网站
  • 建筑公司网站怎么设计seo网站自动发布外链工具
  • icp主体备案号 网站备案号外贸网站建站和推广
  • 个人手机网站大全网络推广发展
  • 用啥网站做首页官方app下载安装
  • 青岛经济新区建设局网站网站收录怎么做
  • 如何才能让自己做的网站百度能搜百度爱采购排名
  • 网站教程网东莞网站推广企业
  • o2o网站线上seo研究中心骗局
  • 建设网站公司哪家好晨阳seo
  • 大良营销网站建设策划北京网上推广
  • 商机加盟好项目下载优化大师
  • 上海市最新消息今天网站seo推广