Требуется программист в Зеленограде
- обработка данных с датчиков; ColdFire; 40 тыс. e-mail:jobsmp@pochta.ru |
module adi_sdram (clk,
rst_in_n,
busy,
// ADI Parallel port
pp_ad_h,
pp_ad_l,
pp_ale,
pp_wr_n,
pp_rd_n,
// SDRAM
sdram_cke,
sdram_cs_n,
sdram_we_n,
sdram_ras_n,
sdram_cas_n,
sdram_ba,
sdram_a,
sdram_dq
);
input clk;
input rst_in_n;
output busy;
input [7:0] pp_ad_h;
inout [7:0] pp_ad_l;
input pp_ale;
input pp_wr_n;
input pp_rd_n;
output sdram_cke;
output sdram_cs_n;
output sdram_we_n;
output sdram_ras_n;
output sdram_cas_n;
output [1:0] sdram_ba;
output [11:0] sdram_a;
inout [7:0] sdram_dq;
//---------------------------------------------------------------------------
// Reset Synch
//
// Ensure reset negates synchronously to clock
//---------------------------------------------------------------------------
reg rst_s1_n;
reg rst_n;
always @(posedge clk)
begin
rst_s1_n <= rst_in_n;
rst_n <= rst_in_n & rst_s1_n;
end
//---------------------------------------------------------------------------
// Address capture register and decode
//
// The 16 address msbs are captured in an asynch reg by ALE. If the address
// 0xffff then any further read or write cycles are directed at the internal
// registers. LSBs are captured during write cycles.
//
// LSBs of address
//---------------------------------------------------------------------------
reg read;
reg write;
reg [15:0] ale_reg;
always @(pp_ale or pp_ad_h or pp_ad_l)
if (pp_ale)
ale_reg <= {pp_ad_h, pp_ad_l};
reg [7:2] reg_addr;
always @(pp_wr_n or pp_rd_n or pp_ad_h)
if ((~pp_wr_n | ~pp_rd_n) & (pp_ad_h[1:0] == 2'b00))
reg_addr <= pp_ad_h[7:2];
wire reg_space = (ale_reg == 16'hffff);
wire init_reg = reg_space & write & (reg_addr == 6'h0);
wire refresh_reg = reg_space & write & (reg_addr == 6'h1);
wire open_rd = reg_space & write & (reg_addr == 6'h2);
wire open_wr = reg_space & write & (reg_addr == 6'h3);
wire power_down = reg_space & write & (reg_addr == 6'h4);
wire power_up = reg_space & write & (reg_addr == 6'h5);
wire read_mem = read & ~reg_space;
wire write_mem = write & ~reg_space;
//---------------------------------------------------------------------------
// Read/Write detectors
//
// Reads and writes are always 4 bytes. For writes we use an asynch register
// to detect when the last byte is written. For reads we detect when the
// first byte is read. These requests are then synched to the local clock.
//---------------------------------------------------------------------------
reg rd_req;
reg wr_req;
wire clr_rd;
wire clr_wr;
always @(rst_n or pp_rd_n or pp_ad_h or clr_rd)
if (~rst_n)
rd_req <= 1'b0;
else if (~pp_rd_n & (pp_ad_h[1:0] == 2'b00))
rd_req <= 1'b1;
else if (clr_rd)
rd_req <= 1'b0;
always @(rst_n or pp_wr_n or pp_ad_h or clr_wr)
if (~rst_n)
wr_req <= 1'b0;
else if (~pp_wr_n & (pp_ad_h[1:0] == 2'b00))
wr_req <= 1'b1;
else if (clr_wr)
wr_req <= 1'b0;
reg rd_req_s1;
reg wr_req_s1;
always @(posedge clk or negedge rst_n)
if (~rst_n)
begin
rd_req_s1 <= 1'b0;
read <= 1'b0;
wr_req_s1 <= 1'b0;
write <= 1'b0;
end
else
begin
rd_req_s1 <= rd_req;
read <= rd_req_s1 & ~clr_rd;
wr_req_s1 <= wr_req;
write <= wr_req_s1;
end
//---------------------------------------------------------------------------
// Write buffer
//
// Asynch registers to capture four bytes of write data.
//---------------------------------------------------------------------------
reg [31:0] wr_buffer;
always @(pp_wr_n or pp_ad_h or pp_ad_l)
if (~pp_wr_n)
case (pp_ad_h[1:0])
2'b00: wr_buffer[7:0] <= pp_ad_l;
2'b01: wr_buffer[15:8] <= pp_ad_l;
2'b10: wr_buffer[23:16] <= pp_ad_l;
default: wr_buffer[31:24] <= pp_ad_l;
endcase
//---------------------------------------------------------------------------
// Read Data
//
// Enabled whenever there's a read cycle, selects byte based on address.
//---------------------------------------------------------------------------
reg [31:0] rd_buffer;
reg [7:0] rd_data;
reg [1:0] rd_addr;
always @(posedge pp_rd_n or posedge pp_ale)
if (pp_ale)
rd_addr <= 2'b0;
else
rd_addr <= rd_addr + 2'b01;
always @(rd_addr or rd_buffer)
case (rd_addr)
2'b00: rd_data <= rd_buffer[7:0];
2'b01: rd_data <= rd_buffer[15:8];
2'b10: rd_data <= rd_buffer[23:16];
default: rd_data <= rd_buffer[31:24];
endcase
wire [7:0] pp_ad_l = pp_rd_n ? {8{1'bz}} : rd_data;
//---------------------------------------------------------------------------
// SDRAM state machine
//
//
//---------------------------------------------------------------------------
reg [5:0] sdram_state;
parameter sdram_nop = 6'h0,
sdram_active1 = 6'h4,
sdram_active2 = 6'h5,
sdram_active3 = 6'h6,
sdram_read1 = 6'h8,
sdram_read2 = 6'h9,
sdram_read3 = 6'ha,
sdram_read4 = 6'hb,
sdram_read5 = 6'hc,
sdram_read6 = 6'hd,
sdram_read7 = 6'he,
sdram_write1 = 6'h10,
sdram_write2 = 6'h11,
sdram_write3 = 6'h12,
sdram_write4 = 6'h13,
sdram_pre1 = 6'h18,
sdram_pre2 = 6'h19,
sdram_pre3 = 6'h1a,
sdram_refresh1 = 6'h20,
sdram_refresh2 = 6'h21,
sdram_refresh3 = 6'h22,
sdram_mode1 = 6'h24,
sdram_mode2 = 6'h25,
sdram_power = 6'h28;
reg init;
always @(posedge clk or negedge rst_n)
if (~rst_n)
init <= 1'b0;
else if (init_reg)
init <= 1'b1;
else if (sdram_state == sdram_mode1)
init <= 1'b0;
reg [3:0] trfc;
always @(posedge clk or negedge rst_n)
if (~rst_n)
trfc <= 4'b0;
else if ((sdram_state == sdram_pre3)
| (sdram_state == sdram_refresh3))
trfc <= 4'd10; // *** parameter
else if (sdram_state == sdram_refresh2)
trfc <= trfc - (|(trfc));
reg [3:0] refresh_burst;
always @(posedge clk or negedge rst_n)
if (~rst_n)
refresh_burst <= 4'b0;
else if (init_reg & (sdram_state == sdram_nop))
refresh_burst <= 4'd1;
else if (refresh_reg & (sdram_state == sdram_nop))
refresh_burst <= 4'd7; // *** parameter
else if (sdram_state == sdram_refresh3)
refresh_burst <= refresh_burst - (|(refresh_burst));
reg [1:0] bank_count;
always @(posedge clk or negedge rst_n)
if (~rst_n)
sdram_state <= sdram_nop;
else
case (sdram_state)
sdram_nop:
begin
if (init_reg | refresh_reg | open_rd | open_wr)
sdram_state <= sdram_pre1;
if (read_mem)
sdram_state <= sdram_read1;
if (write_mem)
sdram_state <= sdram_write1;
if (power_down)
sdram_state <= sdram_power;
end
sdram_active1:
sdram_state <= sdram_active2;
sdram_active2:
sdram_state <= sdram_active3;
sdram_active3:
if (~(&bank_count))
sdram_state <= sdram_active1;
else if (open_rd)
sdram_state <= sdram_read1;
else
sdram_state <= sdram_nop;
sdram_read1: // *** hardwired for cas latency 3
sdram_state <= sdram_read2;
sdram_read2:
sdram_state <= sdram_read3;
sdram_read3:
sdram_state <= sdram_read4;
sdram_read4:
sdram_state <= sdram_read5;
sdram_read5:
sdram_state <= sdram_read6;
sdram_read6:
sdram_state <= sdram_read7;
sdram_read7:
if (sdram_cke & read_mem)
sdram_state <= sdram_read4;
else if (sdram_cke)
sdram_state <= sdram_nop;
else
sdram_state <= sdram_read7;
sdram_write1:
sdram_state <= sdram_write2;
sdram_write2:
sdram_state <= sdram_write3;
sdram_write3:
sdram_state <= sdram_write4;
sdram_write4:
if (write_mem)
sdram_state <= sdram_write1;
else
sdram_state <= sdram_nop;
sdram_pre1:
sdram_state <= sdram_pre2;
sdram_pre2:
sdram_state <= sdram_pre3;
sdram_pre3:
if (open_rd | open_wr)
sdram_state <= sdram_active1;
else
sdram_state <= sdram_refresh1;
sdram_refresh1:
sdram_state <= sdram_refresh2;
sdram_refresh2:
if (trfc == 4'b0)
sdram_state <= sdram_refresh3;
else
sdram_state <= sdram_refresh2;
sdram_refresh3:
if ((refresh_burst == 5'b0) & init)
sdram_state <= sdram_mode1;
else if (refresh_burst == 5'b0)
sdram_state <= sdram_nop;
else
sdram_state <= sdram_refresh1;
sdram_mode1:
sdram_state <= sdram_mode2;
sdram_mode2:
sdram_state <= sdram_nop;
sdram_power:
if (power_up)
sdram_state <= sdram_nop;
default:
sdram_state <= sdram_nop;
endcase
assign clr_rd = (sdram_state == sdram_read4);
assign clr_wr = (sdram_state == sdram_write1)
| (sdram_state == sdram_read1)
| open_wr & (sdram_state == sdram_active1) & (&bank_count)
| (sdram_state == sdram_refresh1);
//---------------------------------------------------------------------------
// SDRAM Control Outputs
//---------------------------------------------------------------------------
reg sdram_cke;
always @(posedge clk or negedge rst_n)
if (~rst_n)
sdram_cke <= 1'b1;
else if ((sdram_state == sdram_power) & power_up)
sdram_cke <= 1'b1;
else if (sdram_state == sdram_power)
sdram_cke <= 1'b0;
else if ((sdram_state == sdram_read6) & ~rd_req_s1)
sdram_cke <= 1'b0;
else if ((sdram_state == sdram_read7) & (rd_req_s1 | wr_req_s1))
sdram_cke <= 1'b1;
reg sdram_cs_n;
always @(posedge clk or negedge rst_n)
if (~rst_n)
sdram_cs_n <= 1'b1;
else if ((sdram_state == sdram_nop) & (init_reg | refresh_reg | open_rd
| open_wr | read_mem | write_mem)
| (sdram_state == sdram_active3) & open_rd & (&bank_count)
| (sdram_state == sdram_pre3)
| (sdram_state == sdram_active3) & ~(&bank_count)
| (sdram_state == sdram_read4)
| (sdram_state == sdram_write4) & write_mem
| (sdram_state == sdram_refresh3) & (|(refresh_burst))
| (sdram_state == sdram_refresh3) & (refresh_burst == 5'b0) & init)
sdram_cs_n = 1'b0;
else
sdram_cs_n <= 1'b1;
reg sdram_ras_n;
always @(posedge clk or negedge rst_n)
if (~rst_n)
sdram_ras_n <= 1'b1;
else if ((sdram_state == sdram_nop) & (init_reg | refresh_reg | open_rd
| open_wr)
| (sdram_state == sdram_pre3)
| (sdram_state == sdram_active3) & ~(&bank_count)
| (sdram_state == sdram_refresh3) & (|(refresh_burst))
| (sdram_state == sdram_refresh3) & (refresh_burst == 5'b0) & init)
sdram_ras_n = 1'b0;
else
sdram_ras_n <= 1'b1;
reg sdram_cas_n;
always @(posedge clk or negedge rst_n)
if (~rst_n)
sdram_cas_n <= 1'b1;
else if ((sdram_state == sdram_nop) & (read_mem | write_mem)
| (sdram_state == sdram_active3) & open_rd & (&bank_count)
| (sdram_state == sdram_pre3) & ~(open_rd | open_wr)
| (sdram_state == sdram_read4)
| (sdram_state == sdram_write4) & write_mem
| (sdram_state == sdram_refresh3) & (|(refresh_burst))
| (sdram_state == sdram_refresh3) & (refresh_burst == 5'b0) & init)
sdram_cas_n = 1'b0;
else
sdram_cas_n <= 1'b1;
reg sdram_we_n;
always @(posedge clk or negedge rst_n)
if (~rst_n)
sdram_we_n <= 1'b1;
else if ((sdram_state == sdram_nop) & (init_reg | refresh_reg | open_rd
| open_wr | write_mem | refresh_reg)
| (sdram_state == sdram_refresh3) & (refresh_burst == 5'b0) & init
| (sdram_state == sdram_write4) & write_mem)
sdram_we_n = 1'b0;
else
sdram_we_n <= 1'b1;
//---------------------------------------------------------------------------
// SDRAM Address
//
//---------------------------------------------------------------------------
reg [11:0] addr_reg;
// bits [11:10] are bank address
always @(posedge clk or negedge rst_n)
if (~rst_n)
addr_reg <= 12'b0;
else if (write & (open_rd | open_wr))
addr_reg <= wr_buffer[11:0];
else if (sdram_state == sdram_read3
| (sdram_state == sdram_read7 & sdram_cke))
addr_reg <= addr_reg + 12'h4;
reg [1:0] sdram_ba;
always @(posedge clk or negedge rst_n)
if (~rst_n)
sdram_ba <= 2'b0;
else if (write & open_rd & (sdram_state == sdram_pre3))
sdram_ba <= addr_reg[11:10];
else if (write & open_wr & (sdram_state == sdram_pre3))
sdram_ba <= addr_reg[11:10];
else if (sdram_state == sdram_active3)
// increment for opening successive banks
sdram_ba <= sdram_ba + 2'b01;
else if ((sdram_state == sdram_nop) & write_mem)
// column address for write access
sdram_ba <= ale_reg[3:2];
else if ((sdram_state == sdram_write4) & write_mem)
// column address for access
sdram_ba <= ale_reg[3:2];
else if ((sdram_state == sdram_nop) & read_mem
| (sdram_state == sdram_read4))
// column address for read access
sdram_ba <= {addr_reg[11:10]};
always @(posedge clk or negedge rst_n)
if (~rst_n)
bank_count <= 2'b00;
else if (write & (sdram_state == sdram_pre3))
bank_count <= 2'b00;
else if (sdram_state == sdram_active3)
// increment for opening successive banks
bank_count <= bank_count + 2'b01;
reg [11:0] sdram_a;
always @(posedge clk or negedge rst_n)
if (~rst_n)
sdram_a <= 12'b0;
else if ((sdram_state == sdram_nop) & (init_reg | refresh_reg | open_rd | open_wr))
// a10 high for precharge all
sdram_a <= 12'b010000000000;
else if ((sdram_state == sdram_refresh3) & init)
// load mode register - CL3, sequential4
sdram_a <= 12'b000000110010;
else if ((sdram_state == sdram_pre3) & (open_rd | open_wr))
// row address
sdram_a <= wr_buffer[23:12];
else if ((sdram_state == sdram_active3) & open_rd & (&bank_count))
// column address for read open & prefetch
sdram_a <= {2'b0, wr_buffer[9:0]};
else if ((sdram_state == sdram_nop) & read_mem
| (sdram_state == sdram_read4))
// column address for read access
sdram_a <= {2'b0, addr_reg[9:0]};
else if ((sdram_state == sdram_nop) & write_mem)
// column address for write access
sdram_a <= {2'b0, ale_reg[1:0], reg_addr[7:2], 2'b0};
else if ((sdram_state == sdram_write4) & write_mem)
// column address for access
sdram_a <= {2'b0, ale_reg[1:0], reg_addr[7:2], 2'b0};
reg [7:0] sdram_dq_out;
always @(posedge clk or negedge rst_n)
if (~rst_n)
sdram_dq_out <= 8'b0;
else
begin
if (write_mem & ((sdram_state == sdram_nop)
| (sdram_state == sdram_write4)))
sdram_dq_out <= wr_buffer[7:0];
if (sdram_state == sdram_write1)
sdram_dq_out <= wr_buffer[15:8];
if (sdram_state == sdram_write2)
sdram_dq_out <= wr_buffer[23:16];
if (sdram_state == sdram_write3)
sdram_dq_out <= wr_buffer[31:24];
end
reg sdram_oe;
always @(posedge clk or negedge rst_n)
if (~rst_n)
sdram_oe <= 1'b0;
else if (write_mem & ((sdram_state == sdram_nop)
| (sdram_state == sdram_write4))
| (sdram_state == sdram_write1)
| (sdram_state == sdram_write2)
| (sdram_state == sdram_write3))
sdram_oe <= 1'b1;
else
sdram_oe <= 1'b0;
wire [7:0] sdram_dq = sdram_oe ? sdram_dq_out : {8{1'bz}};
//---------------------------------------------------------------------------
// Read Buffer
//---------------------------------------------------------------------------
reg sdram_byte3;
always @(posedge clk or negedge rst_n)
if (~rst_n)
sdram_byte3 <= 1'b0;
else
sdram_byte3 <= (sdram_state == sdram_read6);
always @(posedge clk or negedge rst_n)
if (~rst_n)
rd_buffer <= 32'b0;
else
begin
if (sdram_state == sdram_read4)
rd_buffer[7:0] <= sdram_dq;
if (sdram_state == sdram_read5)
rd_buffer[15:8] <= sdram_dq;
if (sdram_state == sdram_read6)
rd_buffer[23:16] <= sdram_dq;
if (sdram_byte3)
rd_buffer[31:24] <= sdram_dq;
end
//---------------------------------------------------------------------------
// Busy
//
// Indicates that controller is busy with refresh or initialization
//---------------------------------------------------------------------------
wire busy = (sdram_state == sdram_active1)
| (sdram_state == sdram_active2)
| (sdram_state == sdram_active3)
| (sdram_state == sdram_pre1)
| (sdram_state == sdram_pre2)
| (sdram_state == sdram_pre3)
| (sdram_state == sdram_refresh1)
| (sdram_state == sdram_refresh2)
| (sdram_state == sdram_refresh3)
| (sdram_state == sdram_mode1)
| (sdram_state == sdram_mode2);
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
endmodule // adi_sdram