当前位置:网站首页>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
边栏推荐
- [OKR target management] case analysis
- Functions and usage of viewflipper
- 【TPM2.0原理及应用指南】 5、7、8章
- 【可信计算】第十三次课:TPM扩展授权与密钥管理
- TaffyDB开源的JS数据库
- Functions and usage of ratingbar
- Create dialog style windows with popupwindow
- 运行yolo v5-5.0版本报错找不到SPPF错误,进行解决
- 【解惑】App处于前台,Activity就不会被回收了?
- cf:C. Factorials and Powers of Two【dp + 排序 + 选不选板子 + 选若干个数等于已知和的最少数】
猜你喜欢
Use onedns to perfectly solve the optimization problem of office network
MRS离线数据分析:通过Flink作业处理OBS数据
仿今日头条APP顶部点击可居中导航
第3章业务功能开发(用户登录)
【网络攻防原理与技术】第6章:特洛伊木马
99%的人都不知道|私有化部署还永久免费的即时通讯软件!
DatePickerDialog and trimepickerdialog
JS pull down the curtain JS special effect display layer
Function and usage of textswitch text switcher
Yarn capacity scheduler (ultra detailed interpretation)
随机推荐
第3章业务功能开发(用户访问项目)
Pytorch中自制数据集进行Dataset重写
【OKR目标管理】案例分析
深度学习-制作自己的数据集
Functions and usage of tabhost tab
What is agile testing
深入浅出【机器学习之线性回归】
【TPM2.0原理及应用指南】 12、13、14章
本周小贴士#140:常量:安全习语
yolo训练过程中批量导入requirments.txt中所需要的包
Robot engineering lifelong learning and work plan-2022-
【OKR目标管理】价值分析
Functions and usage of serachview
利用七种方法对一个文件夹里面的所有图像进行图像增强实战
百度地图自定义样式向右拖拽导致全球地图经度0度无法正常显示
[distributed theory] (I) distributed transactions
做软件测试 掌握哪些技术才能算作 “ 测试高手 ”?
【网络攻防原理与技术】第1章:绪论
Based on pytorch, we use CNN to classify our own data sets
Threshold segmentation based on RGB image and threshold adjustment by sliding