三段式状态机在DDR内存读的应用

/*读仲裁模块,使用轮训方式仲裁,清晰易懂*/
module mem_read_arbi
#(
	parameter MEM_DATA_BITS = 32
)
(
	input rst_n,
	input mem_clk,
	input ch0_rd_burst_req,
	input[9:0] ch0_rd_burst_len,
	input[23:0] ch0_rd_burst_addr,
	output ch0_rd_burst_data_valid,
	output[MEM_DATA_BITS - 1:0] ch0_rd_burst_data,
	output ch0_rd_burst_finish,
	
	input ch1_rd_burst_req,
	input[9:0] ch1_rd_burst_len,
	input[23:0] ch1_rd_burst_addr,
	output ch1_rd_burst_data_valid,
	output[MEM_DATA_BITS - 1:0] ch1_rd_burst_data,
	output ch1_rd_burst_finish,
	
	input ch2_rd_burst_req,
	input[9:0] ch2_rd_burst_len,
	input[23:0] ch2_rd_burst_addr,
	output ch2_rd_burst_data_valid,
	output[MEM_DATA_BITS - 1:0] ch2_rd_burst_data,
	output ch2_rd_burst_finish,
	
	input ch3_rd_burst_req,
	input[9:0] ch3_rd_burst_len,
	input[23:0] ch3_rd_burst_addr,
	output ch3_rd_burst_data_valid,
	output[MEM_DATA_BITS - 1:0] ch3_rd_burst_data,
	output ch3_rd_burst_finish,
	///
	output reg rd_burst_req,
	output reg[9:0] rd_burst_len,
	output reg[23:0] rd_burst_addr,
	input rd_burst_data_valid,
	input[MEM_DATA_BITS - 1:0] rd_burst_data,
	input rd_burst_finish	
);

reg[5:0] read_state = 6'd0;
reg[5:0] read_state_next = 6'd0;
reg[15:0] cnt_timer = 15'd0;
localparam IDLE = 6'd0;

localparam CH0_CHECK = 6'd1;
localparam CH0_BEGIN = 6'd2;
localparam CH0_READ = 6'd3;
localparam CH0_END = 6'd4;

localparam CH1_CHECK = 6'd5;
localparam CH1_BEGIN = 6'd6;
localparam CH1_READ = 6'd7;
localparam CH1_END = 6'd8;

localparam CH2_CHECK = 6'd9;
localparam CH2_BEGIN = 6'd10;
localparam CH2_READ = 6'd11;
localparam CH2_END = 6'd12;

localparam CH3_CHECK = 6'd13;
localparam CH3_BEGIN = 6'd14;
localparam CH3_READ = 6'd15;
localparam CH3_END = 6'd16;

// 2021-02-17 12:11:09
// 这也是一个三段式状态机的程序FSM,有一个定时器,当读数据在0~16'd8000之间,就实现读操作,其它的就是IDLE状态了
// 可能这个定时器的作用就是用来实现DDR的间隔性的读写
// 状态转移

always@(posedge mem_clk or negedge rst_n)
begin
	if(~rst_n)
		read_state <= IDLE;
	else if(cnt_timer > 16'd8000)
		read_state <= IDLE;
	else
		read_state <= read_state_next;
end

always@(posedge mem_clk or negedge rst_n)
begin
	if(~rst_n)
		cnt_timer <= 16'd0;
	else if(read_state == CH0_CHECK)
		cnt_timer <= 16'd0;
	else
		cnt_timer <= cnt_timer + 16'd1;
end

//  2021-02-17 12:17:15
// 状态检测

always@(*)
begin
	case(read_state)
		IDLE:
			read_state_next <= CH0_CHECK;
		//
		CH0_CHECK:
			if(ch0_rd_burst_req && ch0_rd_burst_len != 10'd0)
				read_state_next <= CH0_BEGIN;
			else
				read_state_next <= CH1_CHECK;
		CH0_BEGIN:
			read_state_next <= CH0_READ;
		CH0_READ:
			if(rd_burst_finish)
				read_state_next <= CH0_END;
			else
				read_state_next <= CH0_READ;
		CH0_END:
			read_state_next <= CH1_CHECK;
		//	
		CH1_CHECK:
			if(ch1_rd_burst_req && ch1_rd_burst_len != 10'd0)
				read_state_next <= CH1_BEGIN;
			else
				read_state_next <= CH2_CHECK;
		CH1_BEGIN:
			read_state_next <= CH1_READ;
		CH1_READ:
			if(rd_burst_finish)
				read_state_next <= CH1_END;
			else
				read_state_next <= CH1_READ;
		CH1_END:
			read_state_next <= CH2_CHECK;
		//	
		CH2_CHECK:
			if(ch2_rd_burst_req  && ch2_rd_burst_len != 10'd0)
				read_state_next <= CH2_BEGIN;
			else
				read_state_next <= CH3_CHECK;
		CH2_BEGIN:
			read_state_next <= CH2_READ;
		CH2_READ:
			if(rd_burst_finish)
				read_state_next <= CH2_END;
			else
				read_state_next <= CH2_READ;
		CH2_END:
			read_state_next <= CH3_CHECK;
		//	
		CH3_CHECK:
			if(ch3_rd_burst_req  && ch3_rd_burst_len != 10'd0)
				read_state_next <= CH3_BEGIN;
			else
				read_state_next <= CH0_CHECK;
		CH3_BEGIN:
			read_state_next <= CH3_READ;
		CH3_READ:
			if(rd_burst_finish)
				read_state_next <= CH3_END;
			else
				read_state_next <= CH3_READ;
		CH3_END:
			read_state_next <= CH0_CHECK;		
		default:
			read_state_next <= IDLE;
	endcase
end

// 2021-02-17 12:17:57
// 状态输出

always@(posedge mem_clk or negedge rst_n)
begin
	if(~rst_n)
		begin
			rd_burst_len <= 10'd0;
			rd_burst_addr <= 24'd0;
		end
	else
		begin
			case(read_state)
				CH0_BEGIN:
					begin
						rd_burst_len <= ch0_rd_burst_len;
						rd_burst_addr <= ch0_rd_burst_addr;
					end
				CH1_BEGIN:
					begin
						rd_burst_len <= ch1_rd_burst_len;
						rd_burst_addr <= ch1_rd_burst_addr;
					end
				CH2_BEGIN:
					begin
						rd_burst_len <= ch2_rd_burst_len;
						rd_burst_addr <= ch2_rd_burst_addr;
					end
				CH3_BEGIN:
					begin
						rd_burst_len <= ch3_rd_burst_len;
						rd_burst_addr <= ch3_rd_burst_addr;
					end
				default:
					begin
						rd_burst_len <= rd_burst_len;
						rd_burst_addr <= rd_burst_addr;
					end
			endcase
		end
end

always@(posedge mem_clk or negedge rst_n)
begin
	if(~rst_n)
		rd_burst_req <= 1'b0;
	else if(read_state == CH0_BEGIN || read_state == CH1_BEGIN || read_state == CH2_BEGIN || read_state == CH3_BEGIN)
		rd_burst_req <= 1'b1;
	else if(rd_burst_data_valid || read_state == CH0_CHECK  || read_state == CH1_CHECK  || read_state == CH2_CHECK  || read_state == CH3_CHECK)
		rd_burst_req <= 1'b0;
	else
		rd_burst_req <= rd_burst_req;
end

assign ch0_rd_burst_finish = (read_state == CH0_END);
assign ch1_rd_burst_finish = (read_state == CH1_END);
assign ch2_rd_burst_finish = (read_state == CH2_END);
assign ch3_rd_burst_finish = (read_state == CH3_END);

assign ch0_rd_burst_data_valid = (read_state == CH0_READ || read_state == CH0_END) ? rd_burst_data_valid : 1'b0;
assign ch1_rd_burst_data_valid = (read_state == CH1_READ || read_state == CH1_END) ? rd_burst_data_valid : 1'b0;
assign ch2_rd_burst_data_valid = (read_state == CH2_READ || read_state == CH2_END) ? rd_burst_data_valid : 1'b0;
assign ch3_rd_burst_data_valid = (read_state == CH3_READ || read_state == CH3_END) ? rd_burst_data_valid : 1'b0;

assign ch0_rd_burst_data = (read_state == CH0_READ) ? rd_burst_data : {MEM_DATA_BITS{1'd0}};
assign ch1_rd_burst_data = (read_state == CH1_READ) ? rd_burst_data : {MEM_DATA_BITS{1'd0}};
assign ch2_rd_burst_data = (read_state == CH2_READ) ? rd_burst_data : {MEM_DATA_BITS{1'd0}};
assign ch3_rd_burst_data = (read_state == CH3_READ) ? rd_burst_data : {MEM_DATA_BITS{1'd0}};
endmodule 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值