当前位置:网站首页>SOC_ SD_ DATA_ FSM
SOC_ SD_ DATA_ FSM
2022-07-05 07:07:00 【Eight four one one】
1. Interface
- Normal clock reset soft reset
- from sd Stuck here in_data_ready、in_sd_data、in_data_direction
- from fifo From the module sd_fifo_full
- Need to receive the sent byte And the number of blocks ,need_to_receive_byte、need_to_receive_block etc.
- Data transmission bit width in_data_width, Yes 1 Line and 4 Line transmission
- Read data timeout in_read_to
- Status signal to the younger brother module current_state、next_state
- Send and receive bit Count and counter
- crc State count receive_crc_status_counter
- Format intermediate signal EZZS Count ,interval_counter
- Transmission end signal out_transfer_complete、one_bk_re_end
input in_sd_clk; //clock for sd card
input hrst_n; //ahb reset signal
input in_soft_reset; //software reset
input in_data_ready; // from sd if Of data_fsm_ready bring a person to the presence of sb.
input sd_fifo_full;
input [3:0] in_sd_data; //data input from sd card It's usually only used for [0]
input in_data_direction; //data direction 1:write 0:read
input [10:0] need_to_receive_byte; //block length
input [10:0] need_to_receive_block; //block number
input [31:0] need_to_send_byte; //block length
input [31:0] need_to_send_block; //block number
input in_data_width; //data width 1:4bit 0:1bit
input [31:0] in_read_to; //time out of read data fsm
output [3:0] current_state; //current state of data fsm
output [3:0] next_state; //next state of data fsm
output has_send_bit_counter_en;//has send bit counter enable
output [3:0] send_crc_counter; //has sent crc bits counter
output [13:0] has_send_bit; //has send data bits counter
output [1:0] receive_crc_status_counter; //has receive crc status bits counter
output [13:0] has_receive_bit; //has receive data bits counter
output out_transfer_complete; //indicate data transfer has completed
output [1:0] interval_counter; //time interval between data end bit and crc status
output out_read_to_error; //read timeout error flag Give to the sd if
output one_bk_re_end;
2. State machine
① Describe the transition of state
always @ (posedge in_sd_clk or negedge hrst_n) begin
if(!hrst_n)
current_state <= `CMD_STATE_STOP;
else if(!in_soft_reset)
current_state <= `CMD_STATE_STOP;
else
current_state <= next_state;
end
② Combinational logic state jump , And assign the corresponding enable
Status introduction , There are many states of this module , I just abbreviated , Anyway, I can understand
- STOP : Stop state ,in_data_ready Enter when high availability IDLE state
- IDLE: Read / write judgment status ,in_data_direction High effective time , Express host Prepare to send data ,WAIT_SEND state , conversely , said host Ready to receive data , Get into WAIT_RECEIVE state
- WAIT_RECEIVE : Read operation readiness , First, judge whether the data block meets the requirements , If you are satisfied, jump into STATE_STOP, And give the status signal read_to_error; Last , Detect the data line data[0] Is it low effective , If it works, jump into RECEIVE state , Otherwise keep ;
- RECEIVE : Data reading operation processing process , And need to judge each piece byte Whether the data has been read , If you are satisfied, jump into RECEIVE_CRC state , Otherwise keep ;
- RECEIVE_CRC : Judge each piece crc Whether the data has been read , If you are satisfied, jump into RECEIVE_END_BIT state , Otherwise keep ;
- RECEIVE_END_BIT : First, judge whether the data block meets the requirements , If you are satisfied, jump into STOP, If you are not satisfied, jump into WAIT_RECEIVE state ;
- WAIT_SEND : Data output waiting state , In terms of fifo When it is full , Judge whether all data blocks have been sent , If you are satisfied, jump into STOP state , Otherwise to data[0] Data to determine , Highly effective , Jump in SNED_Z state , Otherwise keep ;
- SNED_Z: No data processing , Get into DATA_STATE_SNED_P state ;
- SNED_P: Bus direction changes direction , Get into SNED_START_BIT state ;
- SNED_START_BIT: Start data sending status , Jump in STATE_SEND state ;
- SEND: Data sending status , A single piece of data is all bit After sending , Get into STATE_SEND_CRC state , Otherwise keep ;
- SEND_CRC:CRC Data sending status , After completion , Jump in STATE_SEND_END_BIT;
- SEND_END_BIT: End bit sending status , It is also used for direction switching of data lines ( Status middle point ), Get into RECEIVE_CRC_STATUS state ;
- RECEIVE_CRC_STATUS: received crc3 individual bit And one. ‘E’ after , Get into SEND_BUSY state ;
- SEND_BUSY: Judge the status when the data block transmission ends , all block End of sending , Jump in STATE_STOP state , Stop operation . otherwise , Get into DATA_STATE_WAIT_SEND state , Wait for the start of the next block data transmission ;
The jump of state is also accompanied by corresponding enablers such as :
- receive bit Count enable has_receive_bit_counter_en
- send out bit Count enable has_send_bit_counter_en
- receive block Count enable has_receive_block_counter_en
- send out block Count enable has_send_block_counter_en
- receive crc Count enable receive_crc_counter_en
- send out crc Count enable send_crc_counter_en
- Read timeout count enable read_resp_time_counter_en
- middle EZZS Data count enable interval_counter_en
- receive crc State count receive_crc_status_counter_en
- One transmission completion signal out_transfer_complete
always @(*) begin
out_read_to_error = 1'b0;
case (current_state)
`DATA_STATE_STOP: //0
begin
has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
if(in_data_ready)
next_state = `DATA_STATE_IDLE;
else
next_state = `DATA_STATE_STOP;
end
`DATA_STATE_IDLE: //1
//IDLE State judgment read / Write sd, Enter the read-write waiting state
begin
has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
if(!in_data_direction)
next_state = `DATA_STATE_WAIT_RECEIVE;
else
next_state = `DATA_STATE_WAIT_SEND;
end
`DATA_STATE_WAIT_RECEIVE: //2
// Data waiting to be received : all blcok Finished STOP; Read timeout STOP;
// Start bit of received data data[0]==0, Enter data receiving mode
begin
has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
if (has_receive_block == need_to_receive_block)
begin
next_state = `DATA_STATE_STOP;
out_transfer_complete = 1'b1;
end
else if (read_resp_time_counter == in_read_to)
begin
next_state = `DATA_STATE_STOP;
out_read_to_error = 1'b1;
end
else begin
if(!in_sd_data[0])
next_state = `DATA_STATE_RECEIVE;
else begin
next_state = `DATA_STATE_WAIT_RECEIVE;
read_resp_time_counter_en = 1'b1;
end
end
end
`DATA_STATE_RECEIVE: //3
// Data receiving status , Enable reception bit Counter , Need to receive bit All received
// Enter receive crc The state of ,
begin
//has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
if(!in_data_width) begin
if (has_receive_bit == need_to_receive_bit - 1)
begin
next_state = `DATA_STATE_RECEIVE_CRC;
has_receive_bit_counter_en = 1'b0;
end
else begin
next_state = `DATA_STATE_RECEIVE;
has_receive_bit_counter_en = 1'b1;
end
end
else begin
if (has_receive_bit_4 == (need_to_receive_bit_4 - 1))
begin
next_state = `DATA_STATE_RECEIVE_CRC;
has_receive_bit_counter_en = 1'b0;
end
else begin
next_state = `DATA_STATE_RECEIVE;
has_receive_bit_counter_en = 1'b1;
end
end
end
`DATA_STATE_RECEIVE_CRC: //4
// receive crc state , Enable reception crc Counter , After receiving, enter , receive end_bit state
begin
has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
//receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
if(receive_crc_counter == 15) begin
next_state =`DATA_STATE_RECEIVE_END_BIT;
receive_crc_counter_en = 1'b0;
end
else begin
next_state = `DATA_STATE_REVEIVE_CRC;
receive_crc_counter_en = 1'b1;
end
end
`DATA_STATE_RECEIVE_END_BIT: //5
// receive end_bit, All block After receiving, return to STOP
// otherwise blcok The counter is enabled , Transfer to waiting for reception , Enable is released , amount to block The count only adds 1
begin
has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
//has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
if(has_receive_block == (need_to_receive_block - 1)) begin
next_state = `DATA_STATE_STOP;
has_receive_block_counter_en = 1'b0;
out_transfer_complete = 1'b1;
end
else begin
next_state = `DATA_STATE_WAIT_RECEIVE;
has_receive_block_counter_en = 1'b1;
end
end
`DATA_STATE_WAIT_SEND: //6
begin
has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
if(sd_fifo_full) begin
if(has_send_block == need_to_send_block)
begin
next_state = `DATA_STATE_STOP;
out_transfer_complete = 1'b1;
end
else begin
// if (!in_sd_data[0])
if (in_sd_data[0])
next_state = `DATA_STATE_WAIT_SEND;
else
next_state = `DATA_STAET_SEND_Z;
end
end
else
next_state = `DATA_STATE_WAIT_SEND;
end
`DATA_STATE_SEND: //7
// Enable sending bit Count , After sending data, prepare to send crc,
begin
has_receive_bit_counter_en = 1'b0;
//has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
if (!in_data_width)
begin
if (has_send_bit == (need_send_bit - 1))
begin
next_state = `DAYA_STATE_SEND_CRC;
has_send_bit_counter_en = 1'b0;
end
else begin
next_state = `DATA_STATE_SEND;
has_send_bit_counter_en = 1'b1;
end
end
else begin
if (has_send_bit == (need_to_seed_bit_4 - 1))
begin
next_state = `DAYA_STATE_SEND_CRC;
has_send_bit_counter_en = 1'b0;
end
else begin
next_state = `DATA_STATE_SEND;
has_send_bit_counter_en = 1'b1;
end
end
end
`DATA_STATE_SEND_CRC: //8
// Enable sending crc bit Count , Finished sending crc Ready to send end bit
begin
has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
//send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
if (send_crc_counter == 15)
begin
next_state = `DATA_STATE_SEND_END_BIT;
send_crc_counter_en = 1'b0;
end
else begin
next_state = `DATA_STATE_SEND_CRC;
send_crc_counter_en = 1'b1;
end
end
`DATA_STATE_SEND_END_BIT: //9
// Finished sending endbit , Prepare to receive the signal whether the data is correct ,
// Here should add a better state , Instead of counting
begin
has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
// here 4 Receive in cycles EZZS
if (interval_counter == 3)
begin
next_state = `DATA_STATE_RECEIVE_CRC_STATUS;
interval_counter_en = 1'b0;
end
else begin
next_state = `DATA_STATE_SNED_END_BIT;
interval_counter_en = 1'b1;
end
end
`DATA_STATE_RECEIVE_CRC_STATUS ://10
begin
has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
// here 4 Receive in cycles status(3bit)+E
if (receive_crc_status_counter == 3)
begin
next_state = `DATA_STATE_SEND_BUSY;
receive_crc_status_counter_en = 1'b0;
end
else begin
next_state = `DATA_STATE_RECEIVE_CRC_STATUS;
receive_crc_status_counter_en = 1'b1;
end
end
`DATA_STATE_SEND_BUSY: //11
// Judge the status when the data block transmission ends , all block End of sending ,
// Jump in STATE_STOP state , Stop operation .
// otherwise , Get into DATA_STATE_WAIT_SEND state , Wait for the start of the next block data transmission .
begin
has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
//has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
if (has_send_block == (need_to_send_block - 1))
begin
next_state = `DATA_STATE_STOP;
has_send_block_counter_en = 1'b0;
out_transfer_complete = 1'b1;
end
else begin
next_state = `DATA_STATE_WAIT_SEND;
has_send_block_counter_en = 1'b1;
end
end
`DATA_STATE_SEND_START_BIT: //12
begin
has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
next_state = `DATA_STATE_SEND;
end
`DATA_STATE_SEND_Z:
begin
has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
next_state = `DATA_STATE_SEND_P;
end
`DATA_STATE_SEND_P:
begin
has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
next_state = `DATA_STATE_SEND_START_BIT;
end
default:
begin
has_receive_bit_counter_en = 1'b0;
has_send_bit_counter_en = 1'b0;
has_receive_block_counter_en = 1'b0;
has_send_block_counter_en = 1'b0;
receive_crc_counter_en = 1'b0;
read_resp_time_counter_en = 1'b0;
send_crc_counter_en = 1'b0;
interval_counter_en = 1'b0;
receive_crc_status_counter_en = 1'b0;
out_transfer_complete = 1'b0;
next_state = `DATA_STATE_STOP;
end
endcase
end
3.one_bk_re_end The birth of
- stay DATA_STATE_RECEIVE_END_BIT State to one_bk_re_end_tp Set up 1
- take one_bk_re_end_tp Take a picture to one_bk_re_end Output , It can guarantee the timing
assign one_bk_re_end_tp = (current_state == `DATA_STATE_RECEIVE_END_BIT);
always @(posedge in_sd_clk or negedge hrst_n) begin
if (!hrst_n)
one_bk_re_end <= 1'b0;
else
one_bk_re_end <= one_bk_re_end_tp;
4. Some counters
- has_receive_bit Count
always @(posedge in_sd_clk or negedge hrst_n) begin
if (!hrst_n)
has_receive_bit <= 14'b0;
else if (!in_soft_reset)
has_receive_bit <= 14'b0;
else if (current_state == `DATA_STATE_RECEIVE_CRC)
has_receive_bit <= 14'b0;
else if (has_receive_bit == (need_to_send_block - 1))
has_receive_bit <= 14'b0;
else if (has_receive_bit_counter_en)
has_receive_bit <= has_receive_bit + 1;
end
- read_resp_time_counter Count
always @(posedge in_sd_clk or negedge hrst_n) begin
if (!hrst_n)
read_resp_time_counter <= 32'b0;
else if (!in_soft_reset)
read_resp_time_counter <= 32'b0;
else if (current_state == `DATA_STATE_STOP)
read_resp_time_counter <= 32'b0;
else if (read_resp_time_counter == in_read_to)
read_resp_time_counter <= 32'b0;
else if (read_resp_time_counter_en)
read_resp_time_counter <= read_resp_time_counter + 1;
end
- has_send_bit Count
always @(posedge in_sd_clk or negedge hrst_n) begin
if (!hrst_n)
has_send_bit <= 14'b0;
else if (!in_soft_reset)
has_send_bit <= 14'b0;
else if (current_state == `DATA_STATE_SEND_CRC)
has_send_bit <= 14'b0;
else if (has_send_bit_counter_en)
has_send_bit <= has_send_bit + 1;
end
- receive_crc_counter
always @(posedge in_sd_clk or negedge hrst_n) begin
if (!hrst_n)
receive_crc_counter <= 14'b0;
else if (!in_soft_reset)
receive_crc_counter <= 14'b0;
else if (receive_crc_counter == 15)
receive_crc_counter <= 14'b0;
else if (receive_crc_counter_en)
receive_crc_counter <= receive_crc_counter + 1;
end
- has_receive_block
always @(posedge in_sd_clk or negedge hrst_n) begin
if (!hrst_n)
has_receive_block <= 32'b0;
else if (!in_soft_reset)
has_receive_block <= 32'b0;
else if (current_state == `DATA_STATE_STOP)
has_receive_block <= 32'b0;
else if (has_receive_block_counter_en)
has_receive_block <= has_receive_block + 1;
end
- has_send_block
always @(posedge in_sd_clk or negedge hrst_n) begin
if (!hrst_n)
has_send_block <= 32'b0;
else if (!in_soft_reset)
has_send_block <= 32'b0;
else if (current_state == `DATA_STATE_STOP)
has_send_block <= 32'b0;
else if (has_send_block_counter_en)
has_send_block <= has_send_block + 1;
end
- interval_counter
always @(posedge in_sd_clk or negedge hrst_n) begin
if (!hrst_n)
interval_counter <= 2'b0;
else if (!in_soft_reset)
interval_counter <= 2'b0;
else if (interval_counter == 3)
interval_counter <= 2'b0;
else if (interval_counter_en)
interval_counter <= interval_counter + 1;
end
- receive_crc_status_counter
always @(posedge in_sd_clk or negedge hrst_n) begin
if (!hrst_n)
receive_crc_status_counter <= 2'b0;
else if (!in_soft_reset)
receive_crc_status_counter <= 2'b0;
else if (receive_crc_status_counter == 3)
receive_crc_status_counter <= 14'b0;
else if (receive_crc_status_counter_en)
receive_crc_status_counter <= receive_crc_status_counter + 1;
end
- send_crc_counter
always @(posedge in_sd_clk or negedge hrst_n) begin
if (!hrst_n)
send_crc_counter <= 14'b0;
else if (!in_soft_reset)
send_crc_counter <= 14'b0;
else if (send_crc_counter == 15)
send_crc_counter <= 14'b0;
else if (send_crc_counter_en)
send_crc_counter <= send_crc_counter + 1;
end
边栏推荐
猜你喜欢
window navicat连接阿里云服务器mysql步骤及常见问题
【软件测试】06 -- 软件测试的基本流程
Database mysql all
Ros2 - configuration development environment (V)
Ros2 - ros2 vs. ros1 (II)
PHY驱动调试之 --- PHY控制器驱动(二)
Marvell 88e1515 PHY loopback mode test
Mipi interface, DVP interface and CSI interface of camera
Inftnews | drink tea and send virtual stocks? Analysis of Naixue's tea "coin issuance"
Orin installs CUDA environment
随机推荐
Steps and FAQs of connecting windows Navicat to Alibaba cloud server MySQL
Technical conference arrangement
Ros2 - configuration development environment (V)
Ros2 - Service Service (IX)
【obs】x264编码:“buffer_size“
What is linting
扫盲-以太网MII接口类型大全-MII、RMII、SMII、GMII、RGMII、SGMII、XGMII、XAUI、RXAUI
CGroup CPU group source code analysis
Volcano 资源预留特性
Executealways of unity is replacing executeineditmode
1290_FreeRTOS中prvTaskIsTaskSuspended()接口实现分析
Orin installs CUDA environment
window navicat连接阿里云服务器mysql步骤及常见问题
C#学习笔记
ROS2——安装ROS2(三)
Use the Paping tool to detect TCP port connectivity
PowerManagerService(一)— 初始化
Literacy Ethernet MII interface types Daquan MII, RMII, smii, gmii, rgmii, sgmii, XGMII, XAUI, rxaui
Lexin interview process
Skywalking all