📄 maincontrol.v
字号:
`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 17:18:45 01/18/06
// Design Name:
// Module Name: maincontrol
// Project Name:
// Target Device:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
//注意:100M猝发读写:的确切含义是以100M采样,以更高的频率(系统的工作时钟,暂定为105MHz)读写SDRAM,以50M的速度从pci读取数据
//在FPGA本地侧的控制逻辑(从PCI—FIFO读取数据的逻辑)一定要与PCI9054的50M时钟一致
module maincontrol (clk,clk50m,doing_precharge,rd_count,doing_refresh,lwr,blast,ads,sd_data_out,sd_rst,addr,do_write,do_read,do_write_ack,do_read_ack,ainit,FIFO_ad_rd,FIFO_ad_wr,pci_data
,sddataout_reg1);
//-------------------------IO
input clk;
input clk50m;
input doing_precharge;
input doing_refresh;
input [31:0] sd_data_out;
input [1:0]rd_count;
input lwr;
input blast;
input ads;
input do_read_ack;
input do_write_ack;
output sd_rst;
output [12:0] addr;
output do_write;
output do_read;
output ainit;
output FIFO_ad_rd;
output FIFO_ad_wr;
output sddataout_reg1;
inout [31:0] pci_data;
//---------------------------REG
reg sd_rst;
reg [12:0] addr;
reg do_write;
reg do_read;
reg ainit;
reg FIFO_ad_wr;
reg [2:0] rst_counter;
reg [7:0] read_counter;
reg [7:0] write_counter;
reg [31:0] reg_data;
reg [31:0] pci_out_reg;
reg mem_write_ena;
reg [31:0] sddataout_reg1;
reg read_ack_reg1;
reg [3:0] next_state;
//---------------------------------------wire 用于连接FIFO core和逻辑
wire [1:0] rd_count;
wire FIFO_ad_rd;
wire [31:0] mem_data_out;
//---------------------------------------parameter
parameter reset=4'd0,
IDLE=4'd1,
arbitrate =4'd2,
send_write_cmd=4'd3,
write_wait=4'd4,
write_burst=4'd5,
precharge_wait=4'd6,
send_read_cmd=4'd7,
read_wait=4'd8,
burst_read=4'd9;
//-------------------------------------------------------------------FIFO_ad_rd
assign FIFO_ad_rd = do_write_ack;
//--------------------------------------------------------------------
always@(posedge clk)
begin
if(!sd_rst)
begin
read_ack_reg1<=1'b0;
end
else
begin
read_ack_reg1<=do_read_ack;
end
end
//-----------------------------------------------------------------state machine
//各个状态的操作:
always @(posedge clk)
begin
case (next_state)
reset:
begin
sd_rst<=1'b0;
addr<=13'd0;
do_write<=1'b0;
do_read<=1'b0;
ainit<=1'b1;
write_counter<=9'd0;
FIFO_ad_wr<=1'b0;
mem_write_ena<=1'b0; //停止向pcimem写数据
if(rst_counter==3'd7) ////将reset状态延长7个周期
begin
rst_counter<=3'd0;
next_state<=IDLE;
end
else
begin
rst_counter<=rst_counter+1;
next_state<=reset;
end
end
//----------------------------------------------------------------------------------
IDLE:
begin
rst_counter<=3'd0;
sd_rst<=1'b1;
ainit<=1'b0;
do_read<=1'b0;
do_write<=1'b0;
write_counter<=9'd0;
FIFO_ad_wr<=1'b0;//停止向ad FIFO写数据
if(lwr&(!blast)) //每当pci写入数据或命令时,跳转至“判断”状态
next_state<=arbitrate;
else next_state<=IDLE;
end
//------------------------------------------------------------------------------------------------
arbitrate:
begin
if(reg_data==32'd0) //reset命令 ,跳转之reset状态
begin
sd_rst<=1'b0;
next_state<=reset;
end
else if(reg_data==32'd2147479278) //发出读行命令,跳转至send_read_cmd状态
next_state<=send_read_cmd;
else if(reg_data==32'd47) //发出写命令,跳转至send _write_cmd状态
next_state<=send_write_cmd;
else next_state<=IDLE;
end
//-----------------------------------------------------------------------------------------
send_write_cmd:
begin
FIFO_ad_wr<=1'b1; //开始向FIFO写数据
sd_rst<=1'b1;
if(doing_refresh) //如果正在进行refresh,等结束后再写
begin
do_write<=1'b0; //停止向SDRAM写数据
next_state<=send_write_cmd;
end
else
begin
if(rd_count>=2'b01)
begin
do_write<=1'b1;
next_state<=write_wait;
end
else
begin
do_write<=1'b0;
next_state<=send_write_cmd;
end
end
end
//---------------------------------------------------------------------------------------
write_wait: //等待写入开始
begin
FIFO_ad_wr<=1'b1;//将AD数据写入FIFO
sd_rst<=1'b1;
if(do_write_ack) //收到写应答,表示下个周期数据开始有效的写入SDRAM
begin
do_write <=1'b0;
next_state<=write_burst; //进入写猝发
end
else
begin
do_write<=1'b1;
next_state<=write_wait;
end
end
//--------------------------------------------------------------------------------------
write_burst: //等待写猝发结束
begin
FIFO_ad_wr<=1'b1;
sd_rst<=1'b1;
if(do_write_ack)
begin
next_state<=write_burst;
end
else //猝发写入完成
begin
addr<=addr+1; //进行过precharge之后,行地址加1
next_state<=precharge_wait;
end
end
//----------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
precharge_wait: //等待precharge结束
begin
sd_rst<=1'b1;
if(doing_precharge) // 在sdram控制模块中,每写完一行并precharge后,
begin
FIFO_ad_wr<=1'b1;
next_state<=precharge_wait; //等待auto refresh完成
end
else
begin //precharge结束之后
if(addr==13'b1111111111111) //行地址和BANK地址加满
begin
addr<=13'd0; //ba和行地址清零
// FIFO_ad_rd<=1'b0;//停止读AD FIFO
FIFO_ad_wr<=1'b0;//停止向AD FIFO写数据
next_state<=IDLE;
end
else
begin
FIFO_ad_wr<=1'b1;
next_state<=send_write_cmd;
end //没有写完2M的数据,再接着写
//在send_write_cmd状态中等待refresh结束
end
end
//---------------------------------------------------------------------------------
send_read_cmd: //发出读命令
begin
sd_rst<=1'b1;
do_write<=1'b0; //添加,保证稳定
if(doing_refresh) //如果正在进行refresh,等结束后再读
begin
do_read<=1'b0; //停止读SDRAM
next_state<=send_read_cmd;
end
else
begin
do_read<=1'b1;
next_state<=read_wait;
end
end
//--------------------------------------------------------------------------------
//调试屏蔽
read_wait: // 等待读应答信号
begin
sd_rst<=1'b1;
do_write<=1'b0; //添加,保证稳定
// if(do_read_ack) //当收到do_read_ack后表示下一个周期数据有效,开始接受数据
if(read_ack_reg1) //当收到read_ack_reg1后表示下一个周期数据有效,开始接受数据
begin
do_read<=1'b0;
//mem[0]<= sd_data_out;//
mem_write_ena<=1'b1; //开始向pcimem写数据
next_state<=burst_read;
end
else next_state<=read_wait;
end
//----------------------------------------------------------------------------------
burst_read: //读猝发,将SDRAM的数据以行猝发的方式读到FPGA中
begin
sd_rst<=1'b1;
do_write<=1'b0;
// if(mem_addr==9'd256) //到256后清零,有效mem地址是0-255,共256个
if(write_counter==8'd255)
begin
write_counter<=8'd0;
mem_write_ena<=1'b0; //停止向pcimem写数据
addr<=addr+1; //读完一行后,行地址加1
next_state<=IDLE; //写完了一行(256列),进入IDLE状态
end
else
begin
mem_write_ena<=1'b1; //开始向pcimem写数据
write_counter<=write_counter+1;
next_state<= burst_read;
end
end
//------------------------------------------------------------------------------
default:
next_state<=IDLE;
endcase
end
//--------------------------------------------------------------read pci_mem
always@(posedge clk50m or negedge sd_rst) //与pci侧的50M时钟同步
begin
if(!sd_rst)
begin
read_counter<=8'd0;
pci_out_reg<=32'd0;
end
else if((!lwr)&(!ads)) //当pci发出读命令时
begin
if(read_counter==8'd255) //只有发出读命令时才改变地址,否则地址不变
read_counter<=8'd0;
else
begin
read_counter<=read_counter+1;
pci_out_reg<=mem_data_out;
end
end
end
//-----------------------------------------------------------------------------双向总线pci_data的控制
//pci端双向总线的输入,将输入的命令存储在reg_data
always@(posedge clk50m or negedge sd_rst) //与pci侧的50M时钟同步
begin
if(!sd_rst)
reg_data<=32'd0;
else if(lwr&(!blast)) //每当pci写入命令时
reg_data<=pci_data; // 将输入命令寄存
end
//-------------------------------------------------------------------------
//pci端双向总线的输出
assign pci_data = ((!lwr)&(!ads))? pci_out_reg: 32'hzzzzzzzz;//当输出使能时,将pci_mem的数据输出,否则为高阻
//-------------------------------------------------------------------
//using pcimem
pcimem mypcimem(
.addra(write_counter[7:0]),
.addrb(read_counter[7:0]),
.clka(clk),
.clkb(clk50m),
.dina(sd_data_out),
.doutb(mem_data_out),
.wea(mem_write_ena));
always@(posedge clk or negedge sd_rst) //将从sdram中读回的数据用寄存器存储,
begin
if(!sd_rst)
begin
sddataout_reg1<=32'd0;
end
else
begin
sddataout_reg1<=sd_data_out;
end
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -