SDRAM-学习6-仲裁模块

192 阅读2分钟

我们已经完成了初始化模块 自动刷新模块 数据写 数据读模块,其中初始化模块优先级最高。初始化之后才可以进行数据读写,同时为了保持数据就需要间隔进行自动刷新。 多个操作同时请求,或者如果某一操作正在执行,其他操作请求执行,我们需要仲裁模块。

仲裁模块:

image.png

原理

优先级: 自动刷新 数据写 数据读。 每一路请求信号只有在仲裁状态才会被响应,保证每一路信号正在响应不会被其他信号所打断。

波形图

初始化结束开始状态跳转 init_end.

sdram_cs_n sdram_cas_n sdram_ras_n sdram_we_n :分别为sdram_cmd[3] sdram_cmd[2] sdram_cmd[1] sdram_cmd[0]

sdram_ba: init_ba

sdram_addr: init_addr

sdram_cmd: init_cmd

wr_req: 写请求信号由fifo控制模块传入

wr_sdram_en: 写使能信号

wr_data:完成数据写入 wr_end信号拉高 由外部传入

仲裁状态下再去判断其他状态的跳转。

image.png

程序:

(
input wire sys_clk,
input wire sys_rst_n,
input wire [3:0]init_cmd,
input wire [1:0]init_ba,
input wire [12:0]init_addr,
input wire init_end,

input wire aref_req,
input wire [3:0]aref_cmd,
input wire [1:0]aref_ba,
input wire [12:0]aref_addr,
input wire aref_end,

input wire       wr_req,
input wire [3:0] wr_cmd,
input wire [1:0] wr_ba,
input wire [12:0]wr_addr,
input wire       wr_end,
input wire 		  wr_sdram_en,
input wire [15:0]wr_data,

input wire       rd_req,
input wire [3:0] rd_cmd,
input wire [1:0] rd_ba,
input wire [12:0]rd_addr,
input wire       rd_end,
input wire 		  rd_sdram_en,

output reg   aref_en,
output reg   wr_en,
output reg   rd_en,
output wire sdram_cke,
output wire  sdram_cs_n,
output wire  sdram_cas_n,
output wire sdram_ras_n,
output wire sdram_we_n,
output reg [1:0]sdram_ba,
output reg [12:0]sdram_addr,
output wire [15:0]sdram_dq

);
parameter IDLE = 5'b0_0001,
ARBIT = 5'b0_0010,
AREF = 5'b0_0100,
WRITE = 5'b0_1000,
READ = 5'b1_0000;

//空操作指令
parameter NOP = 4'b0111;





reg [4:0] state;
reg [3:0] sdram_cmd;
//状态参数赋值
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		state <= IDLE;
	else
		case(state)
			IDLE:
				if(init_end == 1'b1)
					state <= ARBIT;
				else
					state <= IDLE;
			ARBIT:
				if(aref_req == 1'b1)
					state <= AREF;
				else if(wr_req == 1'b1)
					state <= WRITE;
				else if(rd_req == 1'b1)
					state <= READ;
				else	
					state <= AREF;
		
			
			AREF:
			if(aref_end == 1'b1)
				state <= ARBIT;
			else
				state <= AREF;
			
			WRITE:
			if(wr_end == 1'b1)
				state <= ARBIT;
			else
				state <= WRITE;
			READ:
			if(rd_end == 1'b1)
				state <= ARBIT;
			else
				state <= READ;
			default:
				state <= IDLE;
		
		endcase 

  
//指令赋值  always 组合逻辑赋值  sdram_cmd sdram_ba sdram_addr

always@(*)
	case(state)
			IDLE:
				begin
					sdram_cmd <= init_cmd;
					sdram_ba  <= init_ba;
					sdram_addr<= init_addr;
				
				end 
		
			AREF:
			begin
					sdram_cmd <= aref_cmd;
					sdram_ba  <= aref_ba;
					sdram_addr<= aref_addr;
				
				end 
			
			WRITE:
			begin
					sdram_cmd <= wr_cmd;
					sdram_ba  <= wr_ba;
					sdram_addr<= wr_addr;
				
				end 
			READ:
			begin
					sdram_cmd <= rd_cmd;
					sdram_ba  <= rd_ba;
					sdram_addr<= rd_addr;
				
				end 
			default:
				begin
					sdram_cmd <= NOP;
					sdram_ba  <= 2'b11;
					sdram_addr<= 13'h1fff;
				
				end 
		
		endcase 


//三路使能信号赋值
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		aref_en <= 1'b0;
	else if((state == ARBIT)&& (aref_req == 1'b1))
		aref_en<= 1'b1;
	else if(aref_end == 1'b1)
		aref_en <= 1'b0;
	

always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		wr_en <= 1'b0;
	else if((state == ARBIT)&& (aref_req == 1'b0)&&(wr_req==1'b1))
		wr_en<= 1'b1;
	else if(wr_end == 1'b1)
		wr_en <= 1'b0;


always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		rd_en <= 1'b0;
	else if((state == ARBIT)&& (aref_req == 1'b0)&&(rd_req == 1'b1)&&(wr_req == 1'b0))
		rd_en<= 1'b1;
	else if(rd_end == 1'b1)
		rd_en <= 1'b0;

// 四路信号构成指令,指令有顺序  思路输出信号

assign{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} = sdram_cmd;



//时钟使能信号  始终保持高电平
assign sdram_cke = 1'b1;
//其他时刻保持高阻态 作为输出端口
assign sdram_dq = (wr_sdram_en == 1'b1) ? wr_data:16'bz;








endmodule