目錄
一、任務
二、需求分析
三、Visio圖
四、具體分析
1.需要注意的問題
(1)器件SDRAM需要的時鐘
(2)跨時鐘域(異步FIFO)
2.模塊分析和調用
(1)SDR SDRAM IP核調用
(2)串口收發模塊
(3)調用PLL IP核
(4)調用異步FIFO IP核
讀FIFO
寫FIFO
(5)讀寫控制模塊
五、代碼
(1)top.v
(2)uart_tx.v
(3)uart_rx.v
(4)key_filter.v
(5)sdram_ctrl.v
(6)rw_ctrl.v
六、實驗現象
一、任務
調用SDR SDRAM IP核對SDR SDRAM進行讀寫操作,按鍵按下從SDRAM中讀出10個數據,并在串口助手顯示,用串口助手每發送10個字節數據,就將數據寫入SDRAM中,與SDRAM通信的時鐘為100MHz。
二、需求分析
分析任務,需要調用SDR SDRAM IP核來完成任務,然后還需要按鍵模塊來進行讀操作,還需要串口收發模塊來發送和接收數據,每接收到10個數據就進行寫操作,說明需要FIFO來進行緩存,讀操作也是一樣的,而且這里要注意,SDRAM通信的時鐘是100MHz,就需要PLL IP核來產生時鐘,最后就是需要讀寫操作模塊。(具體看具體分析)
三、Visio圖
四、具體分析
1.需要注意的問題
(1)器件SDRAM需要的時鐘
????????器件SDRAM需要的100MHz時鐘需要進行相位偏移,Slave需要的100MHz時鐘不需要相位偏移,為什么器件SDRAM需要偏移時鐘,就是讓SDRAM在數據的中間采集的數據是穩定的。
(2)跨時鐘域(異步FIFO)
跨時鐘域常用的方法就是:異步FIFO
????????這里涉及50MHz和100MHz,從串口接收模塊是50MHz時鐘,發送給Slave是需要100MHz時鐘,所以必須要使用異步FIFO。
2.模塊分析和調用
(1)SDR SDRAM IP核調用
調用SDR SDRAM IP核
(2)串口收發模塊
串口收發模塊
(3)調用PLL IP核
(4)調用異步FIFO IP核
這里異步FIFO IP要調用兩個一個讀FIFO和一個寫FIFO:
讀FIFO
寫FIFO
(5)讀寫控制模塊
調用的SDR SDRAM IP核的突發長度固定是1,所以這里的連續讀或寫10個數據,就發10個讀指令或寫指令,是一個偽突發。(指令都是由SDR SDRAM IP核內部發送的)
當串口助手發送10個字節數據,狀態由IDLE狀態跳到WRITE狀態,由于這里的寫FIFO是16bit寬度,所以讓這個數據{2{data}},在讀出來的時候截取低8位,當10個數據傳輸完成,進入DONE狀態,再進入IDLE狀態,等待下一次觸發。
當按鍵按下,狀態由IDLE狀態跳到READ狀態,每接收一個數據就發送,當發送10個數據,狀態由READ狀態進入DONE狀態,再進入IDLE狀態,等待下一次觸發。(更具體的可以看rw_ctrl.v)
五、代碼
(1)top.v
module top( input clk ,input rst_n ,//keyinput key_in ,//uart_txinput rx ,//uart_rxoutput tx ,//sdram_ctrloutput clk_100s ,output [12:0] sdram_addr ,//行列地址 output [1:0] sdram_bank ,//bank地址 []output sdram_cas_n,output sdram_cke , output sdram_cs_n , inout [15:0] sdram_dq , output [1:0] sdram_dqm , output sdram_ras_n,output sdram_we_n
);
//key_filter
wire key_down;
//uart_rx
wire uart_rxd ;
wire [7:0] rx_data ;
wire rx_data_vld;
//uart_tx
wire [7:0] tx_data ;
wire tx_data_vld;
wire uart_txd ;
wire ready ;
//pll
wire clk_in ;
wire clk_out;
wire locked ;key_filter u_key_filter(.clk (clk ),.rst_n (rst_n ),.key_in (key_in ),.key_down (key_down )
);uart_rx #( .CLOCK_FRQ(50_000_000),.BAUD(115200),.DATA_LENTH(8) ,.CHECKBIT_SELECT(0),.CHECK_TYPE(0) //偶校驗:0 奇校驗:1
)uart_rx_inst( /*input */.clk (clk ),/*input */.rst_n (rst_n ),/*input */.uart_rxd (rx ),/*output reg [7:0] */.dout (rx_data ),/*output */.dout_vld (rx_data_vld)
);uart_tx #( .CLOCK_FRQ(50_000_000),.BAUD(115200),.DATA_LENTH(8) ,.CHECKBIT_SELECT(0),.CHECK_TYPE(0) //偶校驗:0 奇校驗:1)uart_tx_inst( /*input */.clk (clk ),/*input */.rst_n (rst_n ),/*input [DATA_LENTH-1:0] */.tx_din (tx_data ),/*input */.tx_enable(tx_data_vld),/*output reg */.uart_txd (tx ),/*output reg */.ready (ready ) //忙閑指示信號
);sdram_ctrl u_sdram_ctrl(.clk (clk_in ),.clk_in (clk ),.clk_out (clk ),.rst_n (rst_n ),.rx_data (rx_data ),.rx_data_vld (rx_data_vld ),.ready (ready ),.tx_data (tx_data ),.tx_data_vld (tx_data_vld ),.key_down (key_down ),.sdram_addr (sdram_addr ),.sdram_bank (sdram_bank ),.sdram_cas_n (sdram_cas_n ),.sdram_cke (sdram_cke ),.sdram_cs_n (sdram_cs_n ),.sdram_dq (sdram_dq ),.sdram_dqm (sdram_dqm ),.sdram_ras_n (sdram_ras_n ),.sdram_we_n (sdram_we_n )
);pll_0 u_pll_0(.areset (~rst_n ),.inclk0 (clk ),.c0 (clk_in ),.c1 (clk_out),.locked (locked )
);assign clk_100s = clk_out;endmodule
(2)uart_tx.v
module uart_tx #(parameter CLOCK_FRQ = 50_000_000,BAUD = 9600 ,DATA_LENTH = 8 ,CHECKBIT_SELECT = 0 ,CHECK_TYPE = 0 //偶校驗:0 奇校驗:1
)( input clk ,input rst_n ,input [DATA_LENTH-1:0] tx_din ,input tx_enable,output reg uart_txd ,output reg ready //忙閑指示信號
);
//---------<參數定義>------------------------------------------------//狀態機參數定義localparam IDLE = 5'b00001,START = 5'b00010,DATA = 5'b00100,CHECK = 5'b01000,STOP = 5'b10000;localparam BUAD_MAX = CLOCK_FRQ/BAUD;//---------<內部信號定義>--------------------------------------------reg [4:0] state_c ;reg [4:0] state_n ;reg [15:0] cnt_baud ;//波特率計數器wire add_cnt_baud;wire end_cnt_baud;reg [2:0] cnt_bit ;//數據傳輸的比特計數器wire add_cnt_bit ;wire end_cnt_bit ;reg [7:0] tx_din_r ;//狀態轉移條件定義wire idle2start ;wire start2data ;wire data2check ;wire data2stop ;wire check2stop ;wire stop2idle ;//*******************************************************************
//--tx_din_r
//*******************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begintx_din_r <= 'd0;end else if(tx_enable)begin tx_din_r <= tx_din;end end//*******************************************************************
//--狀態機
//*******************************************************************//第一段:同步時序描述狀態轉移always @(posedge clk or negedge rst_n)begin if(!rst_n)beginstate_c <= IDLE;end else begin state_c <= state_n;end end//第二段:組合邏輯判斷狀態轉移條件,描述狀態轉移規律always @(*) begincase(state_c)IDLE : beginif(idle2start)state_n = START; else state_n = state_c;endSTART : beginif(start2data)state_n = DATA;else state_n = state_c;endDATA : beginif(data2check)state_n = CHECK;else if(data2stop)state_n = STOP;else state_n = state_c;endCHECK : beginif(check2stop)state_n = STOP;else state_n = state_c;endSTOP : beginif(stop2idle)state_n = IDLE; else state_n = state_c;enddefault : state_n = IDLE;endcaseendassign idle2start = (state_c == IDLE ) && tx_enable; assign start2data = (state_c == START) && end_cnt_baud;assign data2check = (state_c == DATA ) && end_cnt_bit && CHECKBIT_SELECT;assign data2stop = (state_c == DATA ) && end_cnt_bit && !CHECKBIT_SELECT;assign check2stop = (state_c == CHECK) && end_cnt_baud;assign stop2idle = (state_c == STOP ) && end_cnt_baud;//*******************************************************************
//--cnt_baud
//*******************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_baud <= 'd0;end else if(add_cnt_baud)begin if(end_cnt_baud)begin cnt_baud <= 'd0;endelse begin cnt_baud <= cnt_baud + 1'b1;end endend assign add_cnt_baud = state_c != IDLE;assign end_cnt_baud = add_cnt_baud && cnt_baud == ((state_c == STOP) ? ((BUAD_MAX>>1)+(BUAD_MAX>>2)) : (BUAD_MAX - 1));//*******************************************************************
//--cnt_bit
//*******************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_bit <= 'd0;end else if(add_cnt_bit)begin if(end_cnt_bit)begin cnt_bit <= 'd0;endelse begin cnt_bit <= cnt_bit + 1'b1;end endend assign add_cnt_bit = state_c == DATA && end_cnt_baud;assign end_cnt_bit = add_cnt_bit && cnt_bit == DATA_LENTH - 1;//*******************************************************************
//--uart_txd
//*******************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)beginuart_txd <= 1'b1;end else begin case (state_c)IDLE : uart_txd <= 1'b1;START : uart_txd <= 1'b0;DATA : uart_txd <= tx_din_r[cnt_bit];//并轉串,LSB// CHECK : uart_txd <= ^tx_din_r + CHECK_TYPE;CHECK : uart_txd <= CHECK_TYPE ? (^tx_din_r + 1'b1) : (^tx_din_r); STOP : uart_txd <= 1'b1;default: uart_txd <= 1'b1;endcaseend end//*******************************************************************
//--ready
//*******************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)beginready <= 'd0;end else begin ready <= state_n == IDLE;end endendmodule
(3)uart_rx.v
module uart_rx #(parameter CLOCK_FRQ = 50_000_000,BAUD = 9600 ,DATA_LENTH = 8 ,CHECKBIT_SELECT = 0 ,CHECK_TYPE = 0 //偶校驗:0 奇校驗:1
)( input clk ,input rst_n ,input uart_rxd ,output reg [7:0] dout ,output dout_vld
);
//---------<參數定義>------------------------------------------------//狀態機參數定義localparam IDLE = 5'b00001,START = 5'b00010,DATA = 5'b00100,CHECK = 5'b01000,STOP = 5'b10000;localparam BUAD_MAX = CLOCK_FRQ/BAUD;//---------<內部信號定義>--------------------------------------------reg [4:0] state_c ;reg [4:0] state_n ;reg [15:0] cnt_baud ;//波特率計數器wire add_cnt_baud;wire end_cnt_baud;reg [2:0] cnt_bit ;//接收bit數量的計數器wire add_cnt_bit;wire end_cnt_bit;reg [2:0] uart_rxd_r ;wire rxd_n_edge ;//狀態轉移條件定義wire idle2start ;wire start2data ;wire data2check ;wire data2stop ;wire check2stop ;wire stop2idle ;//*******************************************************************
//--打三拍(前兩拍同步,后一拍獲得邊沿)
//*******************************************************************//uart_rxd_ralways @(posedge clk or negedge rst_n)begin if(!rst_n)beginuart_rxd_r <= 3'b111;end else begin uart_rxd_r <= {uart_rxd_r[1:0],uart_rxd};end end//rxd_n_edgeassign rxd_n_edge = ~uart_rxd_r[1] & uart_rxd_r[2];//*******************************************************************
//--狀態機
//*******************************************************************//第一段:同步時序描述狀態轉移always @(posedge clk or negedge rst_n)begin if(!rst_n)beginstate_c <= IDLE;end else begin state_c <= state_n;end end//第二段:組合邏輯判斷狀態轉移條件,描述狀態轉移規律always @(*) begincase(state_c)IDLE : beginif(idle2start)state_n = START; else state_n = state_c;endSTART : beginif(start2data)state_n = DATA;else state_n = state_c;endDATA : beginif(data2check)state_n = CHECK;else if(data2stop)state_n = STOP;else state_n = state_c;endCHECK : beginif(check2stop)state_n = STOP;else state_n = state_c;endSTOP : beginif(stop2idle)state_n = IDLE; else state_n = state_c;enddefault : state_n = IDLE;endcaseendassign idle2start = (state_c == IDLE ) && rxd_n_edge;assign start2data = (state_c == START) && end_cnt_baud;assign data2check = (state_c == DATA ) && end_cnt_bit && CHECKBIT_SELECT;assign data2stop = (state_c == DATA ) && end_cnt_bit && !CHECKBIT_SELECT;assign check2stop = (state_c == CHECK) && end_cnt_baud;assign stop2idle = (state_c == STOP ) && end_cnt_baud;//*******************************************************************
//--cnt_baud
//*******************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_baud <= 'd0;end else if(add_cnt_baud)begin if(end_cnt_baud)begin cnt_baud <= 'd0;endelse begin cnt_baud <= cnt_baud + 1'b1;end endend assign add_cnt_baud = state_c != IDLE;assign end_cnt_baud = add_cnt_baud && cnt_baud == ((state_c == STOP) ? ((BUAD_MAX>>1)+(BUAD_MAX>>2)) : (BUAD_MAX - 1));//*******************************************************************
//--cnt_bit
//*******************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_bit <= 'd0;end else if(add_cnt_bit)begin if(end_cnt_bit)begin cnt_bit <= 'd0;endelse begin cnt_bit <= cnt_bit + 1'b1;end endend assign add_cnt_bit = state_c == DATA && end_cnt_baud;assign end_cnt_bit = add_cnt_bit && cnt_bit == DATA_LENTH - 1;//*******************************************************************
//--dout
//*******************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begindout <= 'd0;end else if(state_c == DATA && cnt_baud == (BUAD_MAX>>1) - 1)begin dout[cnt_bit] <= uart_rxd_r[2];// dout <= {uart_rxd_r[2],dout[7:1]};end end//*******************************************************************
//--dout_vld
//*******************************************************************assign dout_vld = stop2idle;endmodule
(4)key_filter.v
module key_filter#(parameter WIDTH = 1,TIME_20MS = 1000_000)( input clk ,input rst_n ,input [WIDTH-1:0] key_in ,output reg [WIDTH-1:0] key_down
);
//---------<參數定義>--------------------------------------------------------- //狀態機參數 獨熱碼編碼localparam IDLE = 4'b0001,//空閑狀態FILTER_DOWN = 4'b0010,//按鍵按下抖動狀態HOLD = 4'b0100,//按鍵穩定按下狀態FILTER_UP = 4'b1000;//按鍵釋放抖動狀態//---------<內部信號定義>-----------------------------------------------------reg [3:0] state_c ;//現態reg [3:0] state_n ;//次態reg [WIDTH-1:0] key_r0 ;//同步打拍reg [WIDTH-1:0] key_r1 ;reg [WIDTH-1:0] key_r2 ;wire [WIDTH-1:0] n_edge ;//下降沿wire [WIDTH-1:0] p_edge ;//上升沿 reg [19:0] cnt_20ms ;//延時計數器(20ms)wire add_cnt_20ms ;wire end_cnt_20ms ; //狀態轉移條件信號wire idle2filter_down ;wire filter_down2idle ;wire filter_down2hold ;wire hold2filter_up ;wire filter_up2hold ;wire filter_up2idle ; //****************************************************************
//--狀態機
//****************************************************************//第一段:時序邏輯描述狀態轉移always @(posedge clk or negedge rst_n)begin if(!rst_n)beginstate_c <= IDLE;end else begin state_c <= state_n;end end//第二段:組合邏輯描述狀態轉移規律和狀態轉移條件always @(*)begin case (state_c)IDLE : begin if(idle2filter_down)begin state_n = FILTER_DOWN;endelse begin // state_n = IDLE;state_n = state_c;endendFILTER_DOWN : begin if(filter_down2idle)begin state_n = IDLE;endelse if(filter_down2hold)begin state_n = HOLD;endelse begin state_n = state_c;endendHOLD : begin if(hold2filter_up)begin state_n = FILTER_UP;endelse begin state_n = state_c;endendFILTER_UP : begin if(filter_up2hold)begin state_n = HOLD;endelse if(filter_up2idle)begin state_n = IDLE;endelse begin state_n = state_c;endenddefault: state_n = IDLE;endcaseendassign idle2filter_down = (state_c == IDLE) && n_edge;assign filter_down2idle = (state_c == FILTER_DOWN) && p_edge;assign filter_down2hold = (state_c == FILTER_DOWN) && end_cnt_20ms && !p_edge;assign hold2filter_up = (state_c == HOLD) && p_edge;assign filter_up2hold = (state_c == FILTER_UP) && n_edge;assign filter_up2idle = (state_c == FILTER_UP) && end_cnt_20ms;//****************************************************************
//--n_edge、p_edge
//**************************************************************** always @(posedge clk or negedge rst_n)begin if(!rst_n)beginkey_r0 <= {WIDTH{1'b1}};key_r1 <= {WIDTH{1'b1}};key_r2 <= {WIDTH{1'b1}};end else begin key_r0 <= key_in;key_r1 <= key_r0;key_r2 <= key_r1; end endassign n_edge = ~key_r1 & key_r2;//下降沿assign p_edge = ~key_r2 & key_r1;//上升沿//****************************************************************
//--cnt_20ms
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_20ms <= 'd0;end else if(add_cnt_20ms)begin if(end_cnt_20ms || filter_down2idle || filter_up2hold)begin cnt_20ms <= 'd0;endelse begin cnt_20ms <= cnt_20ms + 1'b1;end endend assign add_cnt_20ms = (state_c == FILTER_DOWN) || (state_c == FILTER_UP);assign end_cnt_20ms = add_cnt_20ms && cnt_20ms == TIME_20MS - 1;//****************************************************************
//--key_down
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)beginkey_down <= 'd0;end else begin key_down <= filter_down2hold ? ~key_r2 : 1'b0;endendendmodule
(5)sdram_ctrl.v
module sdram_ctrl( input clk ,//100Mhzinput clk_in ,//50Mhzinput clk_out ,//50Mhzinput rst_n ,//uart_rxinput [7:0] rx_data ,input rx_data_vld,//uart_txinput ready ,output [7:0] tx_data ,output tx_data_vld,//key_filterinput key_down ,//sdram memoryoutput [12:0] sdram_addr ,//行列地址 output [1:0] sdram_bank ,//bank地址 output sdram_cas_n,output sdram_cke , output sdram_cs_n , inout [15:0] sdram_dq , output [1:0] sdram_dqm , output sdram_ras_n,output sdram_we_n
);wire [23:0] avm_address ;
wire [15:0] avm_wrdata ;
wire avm_read_n ;
wire avm_write_n ;
wire [15:0] avm_rddata ;
wire avm_rddata_vld ;
wire avm_waitrequest;rw_sdram u_rw_sdram(.clk (clk ),.clk_in (clk_in ),.clk_out (clk_out ),.rst_n (rst_n ),.rx_data (rx_data ),.rx_data_vld (rx_data_vld ),.ready (ready ),.tx_data (tx_data ),.tx_data_vld (tx_data_vld ),.key_down (key_down ),.avm_address (avm_address ),.avm_wrdata (avm_wrdata ),.avm_read_n (avm_read_n ),.avm_write_n (avm_write_n ),.avm_rddata (avm_rddata ),.avm_rddata_vld (avm_rddata_vld ),.avm_waitrequest (avm_waitrequest )
);sdram_intf u_sdram_intf(.avs_address (avm_address ),.avs_byteenable_n (2'b00 ),.avs_chipselect (1'b1 ),.avs_writedata (avm_wrdata ),.avs_read_n (avm_read_n ),.avs_write_n (avm_write_n ),.avs_readdata (avm_rddata ),.avs_readdatavalid (avm_rddata_vld ),.avs_waitrequest (avm_waitrequest),.clk_clk (clk ),.reset_reset_n (rst_n ),.sdram_addr (sdram_addr ),.sdram_ba (sdram_bank ),.sdram_cas_n (sdram_cas_n ),.sdram_cke (sdram_cke ),.sdram_cs_n (sdram_cs_n ),.sdram_dq (sdram_dq ),.sdram_dqm (sdram_dqm ),.sdram_ras_n (sdram_ras_n ),.sdram_we_n (sdram_we_n )
);endmodule
(6)rw_ctrl.v
module rw_sdram#(parameter BURST_LENTH = 10)( input clk ,//100Mhzinput clk_in ,//50Mhzinput clk_out ,//50Mhzinput rst_n ,//uart_rxinput [7:0] rx_data ,input rx_data_vld ,//uart_txinput ready ,output [7:0] tx_data ,output tx_data_vld ,//key_filterinput key_down ,//sdram ip: Avalon-MM Master Interface output [23:0] avm_address ,//{bank[1],row[12:0],bank[0],colum[8:0]} output [15:0] avm_wrdata , output avm_read_n , output avm_write_n , input [15:0] avm_rddata , input avm_rddata_vld ,input avm_waitrequest
);localparam IDLE = 4'b0001,WRITE = 4'b0010,READ = 4'b0100,DONE = 4'b1000;reg [3:0] state_c ;
reg [3:0] state_n ; reg [3:0] cnt_burst ;//突發讀/寫長度計數器
wire add_cnt_burst;
wire end_cnt_burst;
reg [23:0] wr_addr ;//{bank[1:0],rwo[12:0],colum[8:0]}
wire add_wr_addr;
wire end_wr_addr;
reg [23:0] rd_addr ;//{bank[1:0],rwo[12:0],colum[8:0]}
wire add_rd_addr;
wire end_rd_addr;wire idle2write;
wire idle2read ;
wire write2done;
wire read2done ;wire wrfifo_wrreq;
wire wrfifo_rdempty;
wire [3:0] wrfifo_rdusedw;
wire wrfifo_wrfull ;
wire wrfifo_rdreq ;
wire [15:0] wrfifo_q ;wire rdfifo_wrreq ;
wire rdfifo_rdempty;
wire rdfifo_wrfull ;
wire rdfifo_rdreq ;
wire [15:0] rdfifo_q ;//---------<FIFO例化>-------------------------------------------------
wr_fifo u_wr_fifo(.aclr (~rst_n ),.data ({2{rx_data} } ),.rdclk (clk ),.rdreq (wrfifo_rdreq ),.wrclk (clk_in ),.wrreq (wrfifo_wrreq ),.q (wrfifo_q ),.rdempty (wrfifo_rdempty),.rdusedw (wrfifo_rdusedw),.wrfull (wrfifo_wrfull )
);assign wrfifo_wrreq = ~wrfifo_wrfull && rx_data_vld;
assign wrfifo_rdreq = ~wrfifo_rdempty && state_c == WRITE && ~avm_waitrequest;rd_fifo u_rd_fifo(.aclr (~rst_n ),.data (avm_rddata ),.rdclk (clk_out ),.rdreq (rdfifo_rdreq ),.wrclk (clk ),.wrreq (rdfifo_wrreq ),.q (rdfifo_q ),.rdempty (rdfifo_rdempty),.wrfull (rdfifo_wrfull )
);assign rdfifo_wrreq = ~rdfifo_wrfull && avm_rddata_vld;
assign rdfifo_rdreq = ~rdfifo_rdempty && ready;//---------<State Machine>-------------------------------------------------
always @(posedge clk or negedge rst_n)begin if(!rst_n)beginstate_c <= IDLE;end else begin state_c <= state_n;end
endalways @(*) begincase(state_c)IDLE : beginif(idle2write)state_n = WRITE;else if(idle2read)state_n = READ;elsestate_n = state_c;endWRITE : beginif(write2done)state_n = DONE;elsestate_n = state_c;endREAD : beginif(read2done)state_n = DONE;elsestate_n = state_c;endDONE : state_n = IDLE;default : ;endcase
endassign idle2write = (state_c == IDLE) && wrfifo_rdusedw >= BURST_LENTH;
assign idle2read = (state_c == IDLE) && key_down;
assign write2done = (state_c == WRITE) && end_cnt_burst;
assign read2done = (state_c == READ) && end_cnt_burst;//---------<cnt_burst>-------------------------------------------------
always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_burst <= 'd0;end else if(add_cnt_burst)begin if(end_cnt_burst)begin cnt_burst <= 'd0;endelse begin cnt_burst <= cnt_burst + 1'b1;end end
end assign add_cnt_burst = (state_c == WRITE | state_c == READ) && ~avm_waitrequest;
assign end_cnt_burst = add_cnt_burst && cnt_burst == BURST_LENTH - 1;//---------<寫地址>-------------------------------------------------
// always @(posedge clk or negedge rst_n)begin
// if(!rst_n)
// wr_addr <= 24'd0;
// else if(state_c == WRITE && ~avm_waitrequest)
// wr_addr <= wr_addr + 1'b1;
// endalways @(posedge clk or negedge rst_n)begin if(!rst_n)beginwr_addr <= 'd0;end else if(add_wr_addr)begin if(end_wr_addr)begin wr_addr <= 'd0;endelse begin wr_addr <= wr_addr + 1'b1;end end
end assign add_wr_addr = state_c == WRITE && ~avm_waitrequest;
assign end_wr_addr = add_wr_addr && wr_addr == 24'hff_ff_ff;//---------<rd_addr>-------------------------------------------------
always @(posedge clk or negedge rst_n)begin if(!rst_n)beginrd_addr <= 'd0;end else if(add_rd_addr)begin if(end_rd_addr)begin rd_addr <= 'd0;endelse begin rd_addr <= rd_addr + 1'b1;end end
end assign add_rd_addr = state_c == READ && ~avm_waitrequest;
assign end_rd_addr = add_rd_addr && rd_addr == 24'hff_ff_ff;//---------<輸出>-------------------------------------------------
assign avm_address = (state_c == WRITE) ? {wr_addr[23],wr_addr[21:9],wr_addr[22],wr_addr[8:0]} : {rd_addr[23],rd_addr[21:9],rd_addr[22],rd_addr[8:0]} ;
assign avm_wrdata = wrfifo_q;
assign avm_read_n = ~(state_c == READ) ;
assign avm_write_n = ~(state_c ==WRITE);assign tx_data = rdfifo_q[7:0];
assign tx_data_vld = rdfifo_rdreq;endmodule
六、實驗現象
以上就是SDR SDRAM的讀寫。(如果有錯誤的地方,還請大家指出來,謝謝!)