当前位置:网站首页>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
边栏推荐
- 99%的人都不知道|私有化部署还永久免费的即时通讯软件!
- 【网络攻防原理与技术】第5章:拒绝服务攻击
- 【网络攻防原理与技术】第3章:网络侦察技术
- List selection JS effect with animation
- Native JS verification code
- Click on the top of today's headline app to navigate in the middle
- Please insert the disk into "U disk (H)" & unable to access the disk structure is damaged and cannot be read
- 【OKR目标管理】价值分析
- Ratingbar的功能和用法
- 机器视觉(1)——概述
猜你喜欢
随机推荐
【可信计算】第十二次课:TPM授权与会话
【TPM2.0原理及应用指南】 1-3章
【信息安全法律法规】复习篇
本周小贴士#135:测试约定而不是实现
【解惑】App处于前台,Activity就不会被回收了?
Understanding of 12 methods of enterprise management
swiper左右切换滑块插件
In depth understanding of USB communication protocol
Ratingbar的功能和用法
第3章业务功能开发(用户访问项目)
基于PyTorch利用CNN对自己的数据集进行分类
Mrs offline data analysis: process OBS data through Flink job
JS pull down the curtain JS special effect display layer
Sanxian Guidong JS game source code
【网络攻防原理与技术】第3章:网络侦察技术
【TPM2.0原理及应用指南】 12、13、14章
第1章CRM核心业务介绍
[tpm2.0 principle and Application guide] Chapter 1-3
viewflipper的功能和用法
Mysql 索引命中级别分析