当前位置:网站首页>SD_DATA_SEND_SHIFT_REGISTER
SD_DATA_SEND_SHIFT_REGISTER
2022-07-07 15:46:00 【捌肆幺幺】
1.接口
- 时钟复位软复位
- sd卡数据线过来的数据in_sd_data
- 数据传输宽度in_data_width
- 从fifo中读出的数据sd_fifo_rdata、使能sd_fifo_re
- 状态in_current_state、in_next_state
- 发送的crc,需要in_send_crc_counter、out_crc_status_wrong
- 发送的数据信号in_has_send_bit、in_interval_counter、out_serial_data
- 输出数据out_data_half_delay、out_data_dir
- 高速时钟模式in_high_speed_clk
input in_sd_clk; //clock for sd card
input hrst_n; //ahb signal
input in_soft_reset; //software reset
input [3:0] in_sd_data; //data input drom sd card
input [31:0] sd_fifo_rdata; //parallel data from tx fifo
input [3:0] in_current_state; //current state of data fsm
input [3:0] in_next_state; //next state of data fsm
input in_data_width; //data width 1:4bit 0:1bit
input [3:0] in_send_crc_counter; //has sent crc bits
input [13:0] in_has_send_bit; //has sent data bits
input [1:0] in_interval_counter; //time interval 数对面crc
input in_high_speed_clk;
output [3:0] out_serial_data; //original serial output data
output sd_fifo_re; //tx fifo read enable
output out_crc_status_wrong; //crc status wrong flag
output [3:0] out_data_dir; //data direction 1:send
output [3:0] out_data_half_delay; //serial output data to sd card
2.内部信号
reg [3:0] out_serial_data;
reg [31:0] shift_reg0;
reg [15:0] crc_reg0;
reg [15:0] crc_reg1;
reg [15:0] crc_reg2;
reg [15:0] crc_reg3;
reg [15:0] crc_shift_reg0;
reg [15:0] crc_shift_reg1;
reg [15:0] crc_shift_reg2;
reg [15:0] crc_shift_reg3;
reg [0:31] data_for_send;
reg [3:0] crc_status_reg;
reg sd_fifo_re;
reg out_crc_status_wrong;
reg [3:0] out_data_half_delay_tp;
reg [3:0] data_dir_nes;
wire [31:0] sd_fifo_rdata_tp;
wire [3:0] data_dir_pos;
3.高速时钟模式
- 由in_high_speed_clk的输入决定out口用哪个数据
assign out_data_half_delay = in_high_speed_clk ? out_serial_data : out_data_half_delay_tp;
assign out_data_dir = in_high_speed_clk ? data_dir_pos :data_dir_nes;
//-------------------------------------------------------
always @(negedge in_sd_clk or negedge hrst_n) begin
if (!hrst_n) begin
out_data_half_delay_tp <= 4'b1111;
end
else begin
out_data_half_delay_tp <= out_serial_data;
//用clk下降沿打拍,延迟半个周期
end
end
//-------------------------------------------------
always @(negedge in_sd_clk or negedge hrst_n) begin
if (!hrst_n) begin
data_dir_nes <= 4'b0
end
else begin
data_dir_nes <= {
data_dir_pos[3],data_dir_pos[2],data_dir_pos[1],data_dir_pos[0]};
end
end
assign data_dir_pos[0] = ( (in_current_state == `DATA_STATE_SEND_P) ||
(in_current_state == `DATA_STATE_SEND_START_BIT) ||
(in_current_state == `DATA_STATE_SEND) ||
(in_current_state == `DATA_STATE_SEND_CRC) ||
((in_current_state == `DATA_STATE_SEND_END_BIT) &&
((in_interval_counter == 0) || (in_interval_counter == 1)))
);
assign data_dir_pos[1] = in_data_width && data_dir_pos[0];
assign data_dir_pos[2] = data_dir_pos[1];
assign data_dir_pos[3] = data_dir_pos[1];
4.移位进行数据的并转串
- 需要移位的数据有out_serial_data、crc_status_reg、crc_shift_reg
- 在每个不同状态,移位不一样的数据
always @(posedge in_sd_clk or negedge hrst_n) begin
if (!hrst_n) begin
shift_reg0 <= 32'b0;
out_serial_data <= 4'b1111;
crc_status_reg <= 4'b0;
crc_shift_reg0 <= 16'b0;
crc_shift_reg1 <= 16'b0;
crc_shift_reg2 <= 16'b0;
crc_shift_reg3 <= 16'b0;
end
else if (!in_soft_reset)
begin
shift_reg0 <= 32'b0;
out_serial_data <= 4'b1111;
crc_status_reg <= 4'b0;
crc_shift_reg0 <= 16'b0;
crc_shift_reg1 <= 16'b0;
crc_shift_reg2 <= 16'b0;
crc_shift_reg3 <= 16'b0;
end
else
begin
if(!in_data_width)
begin
if (in_current_state == `DATA_STATE_SEND_START_BIT)
//send start bit
out_serial_data[0] <= 1'b0;
else if (in_current_state == `DATA_STATE_SEND)
begin
//每32个bit,重新赋一个值(从fifo中读出得到)
if (in_has_send_bit[4:0] == 5'b0)
{
out_serial_data[0],shift_reg0} <= {
sd_fifo_rdata_tp,1'b0};
else
{
out_serial_data[0],shift_reg0} <= {
shift_reg0,1'b0};
//向左移位输出,并行转串行
end
else if (in_current_state == `DATA_STATE_SEND_CRC)
begin
if (in_send_crc_counter == 0)
{
out_serial_data[0],crc_shift_reg0} <= {
crc_reg0,1'b0};
else
{
out_serial_data[0],crc_shift_reg0} <= {
crc_shift_reg0,1'b0};
end
else if (in_current_state == `DATA_STATE_SEND_END_BIT)
begin
out_serial_data[0] <= 1'b1;
end
//DATA_STATE_RECEIVE_CRC_STATUS 这里sd 数据线的方向变化,变为接收crc_status
else if (in_current_state == `DATA_STATE_RECEIVE_CRC_STATUS)
begin
crc_status_reg <= {
crc_status_reg[2:0], in_sd_data[0]};
end
else if (in_current_state == `DATA_STATE_WAIT_SEND)
begin
crc_status_reg <= 4'b0;
end
end
else
begin
if (in_current_state == `DATA_STATE_SEND_START_BIT)
out_serial_data <= 4'b0;
else if (in_current_state == `DATA_STATE_SEND)
begin
if (in_has_send_bit[2:0] == 3'b0)
{
out_serial_data,shift_reg0} <= {
sd_fifo_rdata_tp,4'b0};
else
{
out_serial_data,shift_reg0} <= {
shift_reg0,4'b0};
end
else if (in_current_state == `DATA_STATE_SEND_CRC)
begin
if(in_send_crc_counter == 0)
begin
{
out_serial_data[3],crc_shift_reg3} <= {
crc_reg3,1'b0};
{
out_serial_data[2],crc_shift_reg2} <= {
crc_reg2,1'b0};
{
out_serial_data[1],crc_shift_reg1} <= {
crc_reg1,1'b0};
{
out_serial_data[0],crc_shift_reg0} <= {
crc_reg0,1'b0};
end
else
begin
{
out_serial_data[3],crc_shift_reg3} <= {
crc_shift_reg3,1'b0};
{
out_serial_data[2],crc_shift_reg2} <= {
crc_shift_reg2,1'b0};
{
out_serial_data[1],crc_shift_reg1} <= {
crc_shift_reg1,1'b0};
{
out_serial_data[0],crc_shift_reg0} <= {
crc_shift_reg0,1'b0};
end
end
else if (in_current_state == `DATA_STATE_RECEIVE_CRC_STATUS)
begin
crc_status_reg <= {
crc_status_reg[2:0],in_sd_data[0]};
end
else if (in_current_state ==`DATA_STATE_WAIT_SEND)
crc_status_reg <= 4'b0
end
end
end
5.data_for_send的产生,后面用于计算crc
- 同样的对于从fifo读到的数据进行高位低位变换,记作sd_fifo_rdata_tp
- 当状态为DATA_STATE_SEND时,将sd_fifo_rdata_tp给到data_for_send
assign sd_fifo_rdata_tp ={
sd_fifo_rdata[7:0],sd_fifo_rdata[15:8],sd_fifo_rdata[23:16],sd_fifo_rdata[31:24]};
always @(*) begin
data_for_send = 32'b0;
if (in_current_state == `DATA_STATE_SEND)
data_for_send = sd_fifo_rdata_tp;
end
6.计算crc16
- 在发送状态的时候,一遍发一边在算
always @(posedge in_sd_clk or negedge hrst_n) begin
if (!hrst_n) begin
crc_reg3 <= 16'b0;
crc_reg2 <= 16'b0;
crc_reg1 <= 16'b0;
crc_reg0 <= 16'b0;
end
else if (!in_soft_reset) begin
crc_reg3 <= 16'b0;
crc_reg2 <= 16'b0;
crc_reg1 <= 16'b0;
crc_reg0 <= 16'b0;
end
else if (in_current_state == `DATA_STATE_WAIT_SEND)
begin
crc_reg3 <= 16'b0;
crc_reg2 <= 16'b0;
crc_reg1 <= 16'b0;
crc_reg0 <= 16'b0;
end
else if (in_current_state == `DATA_STATE_SEND)
begin
if (!in_data_width)
begin
crc_reg0[0] <= data_for_send[in_has_send_bit[4:0]] ^ crc_reg0[15];
crc_reg0[1] <= crc_reg0[0];
crc_reg0[2] <= crc_reg0[1];
crc_reg0[3] <= crc_reg0[2];
crc_reg0[4] <= crc_reg0[3];
crc_reg0[5] <= crc_reg0[4] ^ data_for_send[in_has_send_bit[4:0]] ^ crc_reg0[15];
crc_reg0[6] <= crc_reg0[5];
crc_reg0[7] <= crc_reg0[6];
crc_reg0[8] <= crc_reg0[7];
crc_reg0[9] <= crc_reg0[8];
crc_reg0[10] <= crc_reg0[9];
crc_reg0[11] <= crc_reg0[10];
crc_reg0[12] <= crc_reg0[11] ^ data_for_send[in_has_send_bit[4:0] ^ crc_reg0[15]];
crc_reg0[13] <= crc_reg0[12];
crc_reg0[14] <= crc_reg0[13];
crc_reg0[15] <= crc_reg0[14];
end
else
begin
crc_reg3[0] <= data_for_send[{
in_has_send_bit[2:0],2'b0}] ^ crc_reg3[15];
crc_reg3[1] <= crc_reg3[0];
crc_reg3[2] <= crc_reg3[1];
crc_reg3[3] <= crc_reg3[2];
crc_reg3[4] <= crc_reg3[3];
crc_reg3[5] <= crc_reg3[4] ^ data_for_send[{
in_has_send_bit[2:0],2'b0}] ^ crc_reg3[15];
crc_reg3[6] <= crc_reg3[5];
crc_reg3[7] <= crc_reg3[6];
crc_reg3[8] <= crc_reg3[7];
crc_reg3[9] <= crc_reg3[8];
crc_reg3[10] <= crc_reg3[9];
crc_reg3[11] <= crc_reg3[10];
crc_reg3[12] <= crc_reg3[11] ^ data_for_send[{
in_has_send_bit[2:0],2'b0}] ^ crc_reg3[15];
crc_reg3[13] <= crc_reg3[12];
crc_reg3[14] <= crc_reg3[13];
crc_reg3[15] <= crc_reg3[14];
crc_reg2[0] <= data_for_send[{
in_has_send_bit[2:0],2'b0}+1] ^ crc_reg2[15];
crc_reg2[1] <= crc_reg2[0];
crc_reg2[2] <= crc_reg2[1];
crc_reg2[3] <= crc_reg2[2];
crc_reg2[4] <= crc_reg2[3];
crc_reg2[5] <= crc_reg2[4] ^ data_for_send[{
in_has_send_bit[2:0],2'b0}+1] ^ crc_reg2[15];
crc_reg2[6] <= crc_reg2[5];
crc_reg2[7] <= crc_reg2[6];
crc_reg2[8] <= crc_reg2[7];
crc_reg2[9] <= crc_reg2[8];
crc_reg2[10] <= crc_reg2[9];
crc_reg2[11] <= crc_reg2[10];
crc_reg2[12] <= crc_reg2[11] ^ data_for_send[{
in_has_send_bit[2:0],2'b0}+1] ^ crc_reg2[15];
crc_reg2[13] <= crc_reg2[12];
crc_reg2[14] <= crc_reg2[13];
crc_reg2[15] <= crc_reg2[14];
crc_reg1[0] <= data_for_send[{
in_has_send_bit[2:0],2'b0}+2] ^ crc_reg1[15];
crc_reg1[1] <= crc_reg1[0];
crc_reg1[2] <= crc_reg1[1];
crc_reg1[3] <= crc_reg1[2];
crc_reg1[4] <= crc_reg1[3];
crc_reg1[5] <= crc_reg1[4] ^ data_for_send[{
in_has_send_bit[2:0],2'b0}+2] ^ crc_reg1[15];
crc_reg1[6] <= crc_reg1[5];
crc_reg1[7] <= crc_reg1[6];
crc_reg1[8] <= crc_reg1[7];
crc_reg1[9] <= crc_reg1[8];
crc_reg1[10] <= crc_reg1[9];
crc_reg1[11] <= crc_reg1[10];
crc_reg1[12] <= crc_reg1[11] ^ data_for_send[{
in_has_send_bit[2:0],2'b0}+2] ^ crc_reg1[15];
crc_reg1[13] <= crc_reg1[12];
crc_reg1[14] <= crc_reg1[13];
crc_reg1[15] <= crc_reg1[14];
crc_reg0[0] <= data_for_send[{
in_has_send_bit[2:0],2'b0}+3] ^ crc_reg0[15];
crc_reg0[1] <= crc_reg0[0];
crc_reg0[2] <= crc_reg0[1];
crc_reg0[3] <= crc_reg0[2];
crc_reg0[4] <= crc_reg0[3];
crc_reg0[5] <= crc_reg0[4] ^ data_for_send[{
in_has_send_bit[2:0],2'b0}+3] ^ crc_reg0[15];
crc_reg0[6] <= crc_reg0[5];
crc_reg0[7] <= crc_reg0[6];
crc_reg0[8] <= crc_reg0[7];
crc_reg0[9] <= crc_reg0[8];
crc_reg0[10] <= crc_reg0[9];
crc_reg0[11] <= crc_reg0[10];
crc_reg0[12] <= crc_reg0[11] ^ data_for_send[{
in_has_send_bit[2:0],2'b0}+3] ^ crc_reg0[15];
crc_reg0[13] <= crc_reg0[12];
crc_reg0[14] <= crc_reg0[13];
crc_reg0[15] <= crc_reg0[14];
end
end
end
7.fifo读使能
- 分为1线和4线的情况
- 数据发完的时候给出fifo的读使能,表明这一次发完了,需要读下一次的数据
always @(*) begin
sd_fifo_re = 1'b0;
if (!in_data_width)
begin
if(((in_current_state == `DATA_STATE_SEND_START_BIT) && (in_has_send_bit[4:0] == 5'b0)) ||
((in_current_state == `DATA_STATE_SEND) && (in_next_state == `DATA_STATE_SEND) && (in_has_send_bit[4:0] == 5'b11111)))
sd_fifo_re = 1'b1;
end
else begin
if(((in_current_state == `DATA_STATE_SEND_START_BIT) && (in_has_send_bit[2:0] == 3'b0)) ||
((in_current_state == `DATA_STATE_SEND) && (in_next_state == `DATA_STATE_SEND) && (in_has_send_bit[2:0] == 3'b111)))
sd_fifo_re = 1'b1;
end
end
8.crc16的状态
- crc16的状态为3bit数,由crc_status_reg 决定,010表示正常
always @(*) begin
out_crc_status_wrong =1'b0;
if((in_current_state == `DATA_STATE_SEND_BUSY) && !(crc_status_reg == 4'b0010))
out_crc_status_wrong =1'b1;
end
边栏推荐
- 【网络攻防原理与技术】第3章:网络侦察技术
- Show progress bar above window
- 在窗口上面显示进度条
- 机器人工程终身学习和工作计划-2022-
- Main work of digital transformation
- swiper左右切换滑块插件
- 简单的loading动画
- 第3章业务功能开发(实现记住账号密码)
- Supplementary instructions to relevant rules of online competition
- Target detection 1 -- actual operation of Yolo data annotation and script for converting XML to TXT file
猜你喜欢

Mui side navigation anchor positioning JS special effect

线上比赛相关规则补充说明

Functions and usage of serachview

Machine vision (1) - Overview

【信息安全法律法规】复习篇

VSCode关于C语言的3个配置文件

Dateticket and timeticket, functions and usage of date and time selectors

深度学习机器学习各种数据集汇总地址

请将磁盘插入“U盘(H)“的情况&无法访问 磁盘结构损坏且无法读取

【TPM2.0原理及应用指南】 12、13、14章
随机推荐
toast会在程序界面上显示一个简单的提示信息
Understanding of 12 methods of enterprise management
Enum + Validation 的个人最佳实践 demo 分享
Management by objectives [14 of management]
手机版像素小鸟游js戏代码
[distributed theory] (II) distributed storage
Pytorch中自制数据集进行Dataset重写
【深度学习】3分钟入门
使用Stace排除故障的5种简单方法
深入浅出【机器学习之线性回归】
机器视觉(1)——概述
三仙归洞js小游戏源码
zdog.js火箭转向动画js特效
【分布式理论】(二)分布式存储
本周小贴士131:特殊成员函数和`= default`
数字化转型的主要工作
Ratingbar的功能和用法
Main work of digital transformation
第1章CRM核心业务介绍
In depth understanding of USB communication protocol