OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/orpsocv2/rtl
    from Rev 619 to Rev 655
    Reverse comparison

Rev 619 → Rev 655

/verilog/cfi_ctrl/cfi_ctrl.v
0,0 → 1,547
////////////////////////////////////////////////////////////////// ////
//// ////
//// Common Flash Interface (CFI) controller ////
//// ////
//// This file is part of the cfi_ctrl project ////
//// http://opencores.org/project,cfi_ctrl ////
//// ////
//// Description ////
//// See below ////
//// ////
//// To Do: ////
//// - ////
//// ////
//// Author(s): ////
//// - Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.gnu.org/copyleft/lesser.html ////
//// ////
//////////////////////////////////////////////////////////////////////
 
/*
Top level of CFI controller with 32-bit Wishbone classic interface
Intended to be used at about 66MHz with a 32MB CFI flash part with 16-bit
data interface.
 
This module has two configurations - one where it pulls in the CFI control
engine, which is intended to simplify accesses to a CFI flash, such as block
unlock, erase, and programming. The alternate configuration is essentially
mapping Wishbone accesses to the flash's bus.
CFI Engine Wishbone interface:
Basic functionality:
Bits [27:26] decode the operation.
2'b00 : read/write to the flash memory
2'b01 : unlock block
2'b10 : erase block
2'b11 : block registers, other flash control features
0xc00_0000 : block status/control register
bits:
[0]: r/o : CFI controller busy
[1]: w/o : clear flash status register
[2]: w/o : reset flash device and controller
0xc00_0004 : flash device status register
bits
[7:0] : r/o : flash device status register
 
0xe00_0000 : read device identifier information
User is able to access the device identifier information such as:
offset 0x0 : manufacturer code
offset 0x2 : device id
offset bba + 0x4 : block (add increments of 128KB block size)
offset 0xa : read config register
See CFI docs for further details (shift offset left by 1)
0xe01_0000 : CFI query
User is able to access the CFI query information
The hex offsets in the CFI spec should be shifted left by one before
applying to the Wishbone bus.
Addresses under 0x000_0000 cause direct access to the flash
Addresses under 0x400_0000 cause the block (addressed in [24:0]) to be unlocked
Addresses under 0x800_0000 cause the block (addressed in [24:0]) to be erased
*/
 
module cfi_ctrl
(
wb_clk_i, wb_rst_i,
wb_dat_i, wb_adr_i,
wb_stb_i, wb_cyc_i,
wb_we_i, wb_sel_i,
wb_dat_o, wb_ack_o,
wb_err_o, wb_rty_o,
 
 
flash_dq_io,
flash_adr_o,
flash_adv_n_o,
flash_ce_n_o,
flash_clk_o,
flash_oe_n_o,
flash_rst_n_o,
flash_wait_i,
flash_we_n_o,
flash_wp_n_o
);
 
parameter flash_dq_width = 16;
parameter flash_adr_width = 24;
 
parameter flash_write_cycles = 4; // wlwh/Tclk = 50ns / 15 ns (66Mhz)
parameter flash_read_cycles = 7; // elqv/Tclk = 95 / 15 ns (66MHz)
 
parameter cfi_engine = "ENABLED";
 
inout [flash_dq_width-1:0] flash_dq_io;
output [flash_adr_width-1:0] flash_adr_o;
 
output flash_adv_n_o;
output flash_ce_n_o;
output flash_clk_o;
output flash_oe_n_o;
output flash_rst_n_o;
input flash_wait_i;
output flash_we_n_o;
output flash_wp_n_o;
 
 
input wb_clk_i, wb_rst_i;
 
 
input [31:0] wb_dat_i, wb_adr_i;
input wb_stb_i, wb_cyc_i,
wb_we_i;
input [3:0] wb_sel_i;
output reg [31:0] wb_dat_o;
output reg wb_ack_o;
output wb_err_o, wb_rty_o;
 
reg [3:0] wb_state;
generate
if (cfi_engine == "ENABLED") begin : cfi_engine_gen
wire do_rst, do_init, do_readstatus;
wire do_clearstatus, do_eraseblock, do_write,
do_read, do_unlockblock;
 
/* Track when we have new bus accesses and are currently serving them */
reg wb_req_in_progress;
wire wb_req_new;
always @(posedge wb_clk_i)
if (wb_rst_i)
wb_req_in_progress <= 0;
else if (wb_req_new)
wb_req_in_progress <= 1'b1;
else if (wb_ack_o)
wb_req_in_progress <= 0;
assign wb_req_new = (wb_stb_i & wb_cyc_i) & !wb_req_in_progress;
 
/* Registers for interfacing with the CFI controller */
reg [15:0] cfi_bus_dat_i;
wire [15:0] cfi_bus_dat_o;
reg [23:0] cfi_bus_adr_i;
wire cfi_bus_ack_o;
wire cfi_bus_busy_o;
wire cfi_rw_sel;
wire cfi_unlock_sel;
wire cfi_erase_sel;
wire cfi_scr_sel;
wire cfi_readstatus_sel;
wire cfi_clearstatus_sel;
wire cfi_rst_sel;
wire cfi_busy_sel;
wire cfi_readdeviceident_sel;
wire cfi_cfiquery_sel;
 
reg cfi_bus_go;
 
reg cfi_first_of_two_accesses;
assign cfi_rw_sel = wb_adr_i[27:26]==2'b00;
assign cfi_unlock_sel = wb_adr_i[27:26]==2'b01 && wb_we_i;
assign cfi_erase_sel = wb_adr_i[27:26]==2'b10 && wb_we_i;
assign cfi_scr_sel = wb_adr_i[27:26]==2'b11 && wb_adr_i[25:0]==26'd0;
assign cfi_readstatus_sel = wb_adr_i[27:26]==2'b11 &&
wb_adr_i[25:0]==26'd4 && !wb_we_i;
assign cfi_clearstatus_sel = cfi_scr_sel && wb_dat_i[1] && wb_we_i;
assign cfi_rst_sel = cfi_scr_sel && wb_dat_i[2] && wb_we_i;
assign cfi_busy_sel = cfi_scr_sel & !wb_we_i;
assign cfi_readdeviceident_sel = wb_adr_i[27:26]==2'b11 &&
wb_adr_i[25]==1'b1 && !wb_adr_i[16]==1'b1 &&
!wb_we_i;
 
assign cfi_cfiquery_sel = wb_adr_i[27:26]==2'b11 &&
wb_adr_i[25]==1'b1 && wb_adr_i[16]==1'b1 &&
!wb_we_i;
 
assign do_rst = cfi_rst_sel & cfi_bus_go;
assign do_init = 0;
assign do_readstatus = cfi_readstatus_sel & cfi_bus_go;
assign do_clearstatus = cfi_clearstatus_sel & cfi_bus_go;
assign do_eraseblock = cfi_erase_sel & cfi_bus_go;
assign do_write = cfi_rw_sel & wb_we_i & cfi_bus_go ;
assign do_read = cfi_rw_sel & !wb_we_i & cfi_bus_go ;
assign do_unlockblock = cfi_unlock_sel & cfi_bus_go ;
assign do_readdeviceident = cfi_readdeviceident_sel & cfi_bus_go ;
assign do_cfiquery = cfi_cfiquery_sel & cfi_bus_go ;
 
/* Main statemachine */
`define WB_FSM_IDLE 0
`define WB_FSM_CFI_CMD_WAIT 2
always @(posedge wb_clk_i)
if (wb_rst_i) begin
wb_state <= `WB_FSM_IDLE;
cfi_bus_go <= 0;
 
/* Wishbone regs */
wb_dat_o <= 0;
wb_ack_o <= 0;
 
cfi_first_of_two_accesses <= 0;
end
else begin
case (wb_state)
`WB_FSM_IDLE: begin
wb_ack_o <= 0;
cfi_bus_go <= 0;
/* Pickup new incoming accesses */
/* Potentially get into a state where we received a bus request
but the CFI was still busy so waited. In this case we'll get a
ACK from the controller and have a new request registered */
if (wb_req_new) begin
if (cfi_busy_sel) /* want to read the busy flag */
begin
wb_ack_o <= 1;
wb_dat_o <= {30'd0, cfi_bus_busy_o};
end
else if (!cfi_bus_busy_o | (wb_req_in_progress & cfi_bus_ack_o))
begin
if (cfi_rw_sel | cfi_unlock_sel | cfi_erase_sel |
cfi_readstatus_sel | cfi_clearstatus_sel |
cfi_rst_sel | cfi_readdeviceident_sel |
cfi_cfiquery_sel)
begin
wb_state <= `WB_FSM_CFI_CMD_WAIT;
cfi_bus_go <= 1;
if (cfi_rw_sel) begin
/* Map address onto the 16-bit word bus*/
/* Reads always do full 32-bits, so adjust
address accordingly.*/
 
/* setup address and number of cycles depending
on request */
if (wb_we_i) begin /* Writing */
/* Only possible to write shorts at a time */
cfi_bus_dat_i <= wb_sel_i[1:0]==2'b11 ?
wb_dat_i[15:0] :
wb_dat_i[31:16];
cfi_bus_adr_i[23:0] <= wb_adr_i[24:1];
end
else begin /* Reading */
/* Full or part word? */
if ((&wb_sel_i)) begin /* 32-bits */
cfi_first_of_two_accesses <= 1;
cfi_bus_adr_i[23:0] <= {wb_adr_i[24:2],1'b0};
end
else begin /*16-bits or byte */
cfi_bus_adr_i[23:0] <= {wb_adr_i[24:1]};
end
end
end
if (cfi_unlock_sel | cfi_erase_sel)
cfi_bus_adr_i[23:0] <= wb_adr_i[24:1];
if (cfi_readdeviceident_sel)
cfi_bus_adr_i[23:0] <= {wb_adr_i[24:17],1'b0,
7'd0,wb_adr_i[9:1]};
if (cfi_cfiquery_sel)
cfi_bus_adr_i[23:0] <= {14'd0,wb_adr_i[10:1]};
end // if (cfi_rw_sel | cfi_unlock_sel | ...
end // if (!cfi_bus_busy_o | (wb_req_in_progress & ...
end // if (wb_req_new)
end // case: `WB_FSM_IDLE
`WB_FSM_CFI_CMD_WAIT: begin
cfi_bus_go <= 0;
/* Wait for the CFI controller to do its thing */
if (cfi_bus_ack_o) begin
if (cfi_rw_sel) begin
/* Is this the first of two accesses? */
if (cfi_first_of_two_accesses) begin
cfi_bus_adr_i <= cfi_bus_adr_i+1;
cfi_first_of_two_accesses <= 0;
cfi_bus_go <= 1;
/* Dealing with a read or a write */
/*
if (wb_we_i)
cfi_bus_dat_i <= wb_dat_i[31:16];
else
*/
wb_dat_o[31:16] <= cfi_bus_dat_o;
end
else begin
wb_state <= `WB_FSM_IDLE;
wb_ack_o <= 1'b1;
if (!wb_we_i) begin
if (&wb_sel_i)
wb_dat_o[15:0] <= cfi_bus_dat_o;
else begin
case (wb_sel_i)
4'b0001 :
wb_dat_o[31:0] <= {4{cfi_bus_dat_o[7:0]}};
4'b0010:
wb_dat_o[31:0] <= {4{cfi_bus_dat_o[15:8]}};
4'b0011 :
wb_dat_o[31:0] <= {cfi_bus_dat_o,cfi_bus_dat_o};
4'b0100 :
wb_dat_o[31:0] <= {4{cfi_bus_dat_o[7:0]}};
4'b1100 :
wb_dat_o[31:0] <= {cfi_bus_dat_o,cfi_bus_dat_o};
4'b1000 :
wb_dat_o[31:0] <= {4{cfi_bus_dat_o[15:8]}};
endcase // case (wb_sel_i)
end
 
end
end // else: !if(cfi_first_of_two_accesses)
end // if (cfi_rw_sel)
else begin
/* All other accesses should be a single go of the CFI
controller */
wb_state <= `WB_FSM_IDLE;
wb_ack_o <= 1'b1;
/* Get the read status data out */
if (cfi_readstatus_sel)
wb_dat_o <= {4{cfi_bus_dat_o[7:0]}};
if (cfi_readdeviceident_sel | cfi_cfiquery_sel)
wb_dat_o <= {2{cfi_bus_dat_o[15:0]}};
end
end // if (cfi_bus_ack_o)
else if (cfi_rst_sel)begin
/* The reset command won't ACK back over the bus, incase
the FSM hung and it actually reset all of its internals */
wb_state <= `WB_FSM_IDLE;
wb_ack_o <= 1'b1;
end
end // case: `WB_FSM_CFI_CMD_WAIT
endcase // case (wb_state)
end // else: !if(wb_rst_i)
assign wb_err_o = 0;
assign wb_rty_o = 0;
 
cfi_ctrl_engine
# (.cfi_part_wlwh_cycles(flash_write_cycles),
.cfi_part_elqv_cycles(flash_read_cycles)
)
cfi_ctrl_engine0
(
.clk_i(wb_clk_i),
.rst_i(wb_rst_i),
 
.do_rst_i(do_rst),
.do_init_i(do_init),
.do_readstatus_i(do_readstatus),
.do_clearstatus_i(do_clearstatus),
.do_eraseblock_i(do_eraseblock),
.do_unlockblock_i(do_unlockblock),
.do_write_i(do_write),
.do_read_i(do_read),
.do_readdeviceident_i(do_readdeviceident),
.do_cfiquery_i(do_cfiquery),
 
.bus_dat_o(cfi_bus_dat_o),
.bus_dat_i(cfi_bus_dat_i),
.bus_adr_i(cfi_bus_adr_i),
.bus_req_done_o(cfi_bus_ack_o),
.bus_busy_o(cfi_bus_busy_o),
 
.flash_dq_io(flash_dq_io),
.flash_adr_o(flash_adr_o),
.flash_adv_n_o(flash_adv_n_o),
.flash_ce_n_o(flash_ce_n_o),
.flash_clk_o(flash_clk_o),
.flash_oe_n_o(flash_oe_n_o),
.flash_rst_n_o(flash_rst_n_o),
.flash_wait_i(flash_wait_i),
.flash_we_n_o(flash_we_n_o),
.flash_wp_n_o(flash_wp_n_o)
 
);
end // if (cfi_engine == "ENABLED")
else begin : cfi_simple
 
reg long_read;
reg [4:0] flash_ctr;
reg [3:0] wb_state;
 
 
reg [flash_dq_width-1:0] flash_dq_o_r;
reg [flash_adr_width-1:0] flash_adr_o_r;
reg flash_oe_n_o_r;
reg flash_we_n_o_r;
reg flash_rst_n_o_r;
wire our_flash_oe;
assign flash_ce_n_o = 0;
assign flash_clk_o = 1;
assign flash_rst_n_o = flash_rst_n_o_r;
assign flash_wp_n_o = 1;
assign flash_adv_n_o = 0;
assign flash_dq_io = (our_flash_oe) ? flash_dq_o_r :
{flash_dq_width{1'bz}};
assign flash_adr_o = flash_adr_o_r;
assign flash_oe_n_o = flash_oe_n_o_r;
assign flash_we_n_o = flash_we_n_o_r;
 
`define WB_STATE_IDLE 0
`define WB_STATE_WAIT 1
 
assign our_flash_oe = (wb_state == `WB_STATE_WAIT ||
wb_ack_o) & wb_we_i;
always @(posedge wb_clk_i)
if (wb_rst_i)
begin
wb_ack_o <= 0;
wb_dat_o <= 0;
wb_state <= `WB_STATE_IDLE;
flash_dq_o_r <= 0;
flash_adr_o_r <= 0;
flash_oe_n_o_r <= 1;
flash_we_n_o_r <= 1;
flash_rst_n_o_r <= 0; /* active */
long_read <= 0;
flash_ctr <= 0;
end
else begin
if (|flash_ctr)
flash_ctr <= flash_ctr - 1;
case(wb_state)
`WB_STATE_IDLE: begin
/* reset some signals to NOP status */
wb_ack_o <= 0;
flash_oe_n_o_r <= 1;
flash_we_n_o_r <= 1;
flash_rst_n_o_r <= 1;
 
if (wb_stb_i & wb_cyc_i & !wb_ack_o) begin
flash_adr_o_r <= wb_adr_i[flash_adr_width:1];
wb_state <= `WB_STATE_WAIT;
if (wb_adr_i[27]) begin
/* Reset the flash, no matter the access */
flash_rst_n_o_r <= 0;
flash_ctr <= 5'd16;
end
else if (wb_we_i) begin
/* load counter with write cycle counter */
flash_ctr <= flash_write_cycles - 1;
/* flash bus write command */
flash_we_n_o_r <= 0;
flash_dq_o_r <= (|wb_sel_i[3:2]) ? wb_dat_i[31:16] :
wb_dat_i[15:0];
end
else begin
/* load counter with write cycle counter */
flash_ctr <= flash_read_cycles - 1;
if (&wb_sel_i)
long_read <= 1; // Full 32-bit read, 2 read cycles
flash_oe_n_o_r <= 0;
end // else: !if(wb_we_i)
end // if (wb_stb_i & wb_cyc_i)
end
`WB_STATE_WAIT: begin
if (!(|flash_ctr)) begin
if (wb_we_i) begin
/* write finished */
wb_ack_o <= 1;
wb_state <= `WB_STATE_IDLE;
flash_we_n_o_r <= 1;
end
else begin
/* read finished */
if (!(&wb_sel_i)) /* short or byte read */ begin
case (wb_sel_i)
4'b0001,
4'b0100:
wb_dat_o <= {4{flash_dq_io[7:0]}};
4'b1000,
4'b0010:
wb_dat_o <= {4{flash_dq_io[15:8]}};
default:
wb_dat_o <= {2{flash_dq_io}};
endcase // case (wb_sel_i)
wb_state <= `WB_STATE_IDLE;
wb_ack_o <= 1;
flash_oe_n_o_r <= 1;
end
else if (long_read) begin
/* now go on to read next word */
wb_dat_o[31:16] <= flash_dq_io;
long_read <= 0;
flash_ctr <= flash_read_cycles;
flash_adr_o_r <= flash_adr_o_r + 1;
end
else begin
/* finished two-part read */
wb_dat_o[15:0] <= flash_dq_io;
wb_state <= `WB_STATE_IDLE;
wb_ack_o <= 1;
flash_oe_n_o_r <= 1;
end
end
end
end
 
default:
wb_state <= `WB_STATE_IDLE;
endcase // case (wb_state)
end // else: !if(wb_rst_i)
end // block: cfi_simple
endgenerate
 
endmodule // cfi_ctrl
 
/verilog/cfi_ctrl/cfi_ctrl_engine.v
0,0 → 1,479
////////////////////////////////////////////////////////////////// ////
//// ////
//// Common Flash Interface (CFI) controller ////
//// ////
//// This file is part of the cfi_ctrl project ////
//// http://opencores.org/project,cfi_ctrl ////
//// ////
//// Description ////
//// See below ////
//// ////
//// To Do: ////
//// - ////
//// ////
//// Author(s): ////
//// - Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.gnu.org/copyleft/lesser.html ////
//// ////
//////////////////////////////////////////////////////////////////////
/*
CFI controller engine.
Contains main state machine and bus controls.
 
Controlled via a simple interface to a bus controller interface.
For now just implements an asynchronous controller.
do_rst_i - reset the flash device
do_init_i - initialise the device (write "read configuration register")
do_readstatus_i - read the status of the device
do_eraseblock_i - erase a block
do_write_i - write a word an address
do_read_i - read a word from an address
bus_dat_o - data out to bus controller
bus_dat_i - data in from bus controller
bus_req_done_o - bus request done
*/
 
 
module cfi_ctrl_engine
(
 
clk_i, rst_i,
 
do_rst_i,
do_init_i,
do_readstatus_i,
do_clearstatus_i,
do_eraseblock_i,
do_unlockblock_i,
do_write_i,
do_read_i,
do_readdeviceident_i,
do_cfiquery_i,
 
bus_dat_o,
bus_dat_i,
bus_adr_i,
bus_req_done_o,
bus_busy_o,
flash_dq_io,
flash_adr_o,
flash_adv_n_o,
flash_ce_n_o,
flash_clk_o,
flash_oe_n_o,
flash_rst_n_o,
flash_wait_i,
flash_we_n_o,
flash_wp_n_o
 
);
 
parameter flash_dq_width = 16;
parameter flash_adr_width = 24;
input clk_i, rst_i;
input do_rst_i,
do_init_i,
do_readstatus_i,
do_clearstatus_i,
do_eraseblock_i,
do_unlockblock_i,
do_write_i,
do_read_i,
do_readdeviceident_i,
do_cfiquery_i;
output reg [flash_dq_width-1:0] bus_dat_o;
input [flash_dq_width-1:0] bus_dat_i;
input [flash_adr_width-1:0] bus_adr_i;
output bus_req_done_o;
output bus_busy_o;
inout [flash_dq_width-1:0] flash_dq_io;
output [flash_adr_width-1:0] flash_adr_o;
output flash_adv_n_o;
output flash_ce_n_o;
output flash_clk_o;
output flash_oe_n_o;
output flash_rst_n_o;
input flash_wait_i;
output flash_we_n_o;
output flash_wp_n_o;
 
wire clk, rst;
 
assign clk = clk_i;
assign rst = rst_i;
 
reg [5:0] bus_control_state;
reg [flash_dq_width-1:0] flash_cmd_to_write;
 
/* regs for flash bus control signals */
reg flash_adv_n_r;
reg flash_ce_n_r;
reg flash_oe_n_r;
reg flash_we_n_r;
reg flash_wp_n_r;
reg flash_rst_n_r;
reg [flash_dq_width-1:0] flash_dq_o_r;
reg [flash_adr_width-1:0] flash_adr_r;
 
reg [3:0] flash_phy_state;
reg [3:0] flash_phy_ctr;
wire flash_phy_async_wait;
`define CFI_PHY_FSM_IDLE 0
`define CFI_PHY_FSM_WRITE_GO 1
`define CFI_PHY_FSM_WRITE_WAIT 2
`define CFI_PHY_FSM_WRITE_DONE 3
`define CFI_PHY_FSM_READ_GO 4
`define CFI_PHY_FSM_READ_WAIT 5
`define CFI_PHY_FSM_READ_DONE 6
`define CFI_PHY_FSM_RESET_GO 7
`define CFI_PHY_FSM_RESET_WAIT 8
`define CFI_PHY_FSM_RESET_DONE 9
 
/* Defines according to CFI spec */
`define CFI_CMD_DAT_READ_STATUS_REG 8'h70
`define CFI_CMD_DAT_CLEAR_STATUS_REG 8'h50
`define CFI_CMD_DAT_WORD_PROGRAM 8'h40
`define CFI_CMD_DAT_BLOCK_ERASE 8'h20
`define CFI_CMD_DAT_READ_ARRAY 8'hff
`define CFI_CMD_DAT_WRITE_RCR 8'h60
`define CFI_CMD_DAT_CONFIRM_WRITE_RCR 8'h03
`define CFI_CMD_DAT_UNLOCKBLOCKSETUP 8'h60
`define CFI_CMD_DAT_CONFIRM_CMD 8'hd0
`define CFI_CMD_DAT_READDEVICEIDENT 8'h90
`define CFI_CMD_DAT_CFIQUERY 8'h98
 
 
/* Main bus-controlled FSM states */
`define CFI_FSM_IDLE 0
`define CFI_FSM_DO_WRITE 1
`define CFI_FSM_DO_WRITE_WAIT 2
`define CFI_FSM_DO_READ 3
`define CFI_FSM_DO_READ_WAIT 4
`define CFI_FSM_DO_BUS_ACK 5
`define CFI_FSM_DO_RESET 6
`define CFI_FSM_DO_RESET_WAIT 7
 
/* Used to internally track what read more we're in
2'b00 : read array mode
2'b01 : read status mode
else : something else*/
reg [1:0] flash_device_read_mode;
/* Track what read mode we're in */
always @(posedge clk)
if (rst)
flash_device_read_mode <= 2'b00;
else if (!flash_rst_n_o)
flash_device_read_mode <= 2'b00;
else if (flash_phy_state == `CFI_PHY_FSM_WRITE_DONE) begin
if (flash_cmd_to_write == `CFI_CMD_DAT_READ_ARRAY)
flash_device_read_mode <= 2'b00;
else if (flash_cmd_to_write == `CFI_CMD_DAT_READ_STATUS_REG)
flash_device_read_mode <= 2'b01;
else
/* Some other mode */
flash_device_read_mode <= 2'b11;
end
/* Main control state machine, controlled by the bus */
always @(posedge clk)
if (rst) begin
/* Power up and start an asynchronous write to the "read config reg" */
bus_control_state <= `CFI_FSM_IDLE;
flash_cmd_to_write <= 0;
end
else
case (bus_control_state)
`CFI_FSM_IDLE : begin
if (do_readstatus_i) begin
// if (flash_device_read_mode != 2'b01) begin
flash_cmd_to_write <= `CFI_CMD_DAT_READ_STATUS_REG;
bus_control_state <= `CFI_FSM_DO_WRITE;
// end
// else begin
// flash_cmd_to_write <= 0;
// bus_control_state <= `CFI_FSM_DO_READ;
// end
end
if (do_clearstatus_i) begin
flash_cmd_to_write <= `CFI_CMD_DAT_CLEAR_STATUS_REG;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
if (do_eraseblock_i) begin
flash_cmd_to_write <= `CFI_CMD_DAT_BLOCK_ERASE;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
if (do_write_i) begin
flash_cmd_to_write <= `CFI_CMD_DAT_WORD_PROGRAM;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
if (do_read_i) begin
if (flash_device_read_mode != 2'b00) begin
flash_cmd_to_write <= `CFI_CMD_DAT_READ_ARRAY;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
else begin
flash_cmd_to_write <= 0;
bus_control_state <= `CFI_FSM_DO_READ;
end
end
if (do_unlockblock_i) begin
flash_cmd_to_write <= `CFI_CMD_DAT_UNLOCKBLOCKSETUP;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
if (do_rst_i) begin
flash_cmd_to_write <= 0;
bus_control_state <= `CFI_FSM_DO_RESET;
end
if (do_readdeviceident_i) begin
flash_cmd_to_write <= `CFI_CMD_DAT_READDEVICEIDENT;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
if (do_cfiquery_i) begin
flash_cmd_to_write <= `CFI_CMD_DAT_CFIQUERY;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
end // case: `CFI_FSM_IDLE
`CFI_FSM_DO_WRITE : begin
bus_control_state <= `CFI_FSM_DO_WRITE_WAIT;
end
`CFI_FSM_DO_WRITE_WAIT : begin
/* Wait for phy controller to finish the write command */
if (flash_phy_state==`CFI_PHY_FSM_WRITE_DONE) begin
if (flash_cmd_to_write == `CFI_CMD_DAT_READ_STATUS_REG ||
flash_cmd_to_write == `CFI_CMD_DAT_READ_ARRAY ||
flash_cmd_to_write == `CFI_CMD_DAT_READDEVICEIDENT ||
flash_cmd_to_write == `CFI_CMD_DAT_CFIQUERY) begin
/* we just changed the read mode, so go ahead and do the
read */
bus_control_state <= `CFI_FSM_DO_READ;
end
else if (flash_cmd_to_write == `CFI_CMD_DAT_WORD_PROGRAM) begin
/* Setting up to do a word write, go to write again */
/* clear the command, to use the incoming data from the bus */
flash_cmd_to_write <= 0;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
else if (flash_cmd_to_write == `CFI_CMD_DAT_BLOCK_ERASE ||
flash_cmd_to_write == `CFI_CMD_DAT_UNLOCKBLOCKSETUP)
begin
/* first stage of a two-stage command requiring confirm */
bus_control_state <= `CFI_FSM_DO_WRITE;
flash_cmd_to_write <= `CFI_CMD_DAT_CONFIRM_CMD;
end
else
/* All other operations should see us acking the bus */
bus_control_state <= `CFI_FSM_DO_BUS_ACK;
end
end // case: `CFI_FSM_DO_WRITE_WAIT
`CFI_FSM_DO_READ : begin
bus_control_state <= `CFI_FSM_DO_READ_WAIT;
end
`CFI_FSM_DO_READ_WAIT : begin
if (flash_phy_state==`CFI_PHY_FSM_READ_DONE) begin
bus_control_state <= `CFI_FSM_DO_BUS_ACK;
end
end
`CFI_FSM_DO_BUS_ACK :
bus_control_state <= `CFI_FSM_IDLE;
`CFI_FSM_DO_RESET :
bus_control_state <= `CFI_FSM_DO_RESET_WAIT;
`CFI_FSM_DO_RESET_WAIT : begin
if (flash_phy_state==`CFI_PHY_FSM_RESET_DONE)
bus_control_state <= `CFI_FSM_IDLE;
end
default :
bus_control_state <= `CFI_FSM_IDLE;
endcase // case (bus_control_state)
 
/* Tell the bus we're done */
assign bus_req_done_o = (bus_control_state==`CFI_FSM_DO_BUS_ACK);
assign bus_busy_o = !(bus_control_state == `CFI_FSM_IDLE);
 
/* Sample flash data for the system bus interface */
always @(posedge clk)
if (rst)
bus_dat_o <= 0;
else if ((flash_phy_state == `CFI_PHY_FSM_READ_WAIT) &&
/* Wait for t_vlqv */
(!flash_phy_async_wait))
/* Sample flash data */
bus_dat_o <= flash_dq_io;
 
/* Flash physical interface control state machine */
always @(posedge clk)
if (rst)
begin
flash_adv_n_r <= 1'b0;
flash_ce_n_r <= 1'b1;
flash_oe_n_r <= 1'b1;
flash_we_n_r <= 1'b1;
flash_dq_o_r <= 0;
flash_adr_r <= 0;
flash_rst_n_r <= 0;
 
flash_phy_state <= `CFI_PHY_FSM_IDLE;
end
else
begin
case (flash_phy_state)
`CFI_PHY_FSM_IDLE : begin
flash_rst_n_r <= 1'b1;
flash_ce_n_r <= 1'b0;
/* Take address from the bus controller */
flash_adr_r <= bus_adr_i;
 
/* Wait for a read or write command */
if (bus_control_state == `CFI_FSM_DO_WRITE)
begin
flash_phy_state <= `CFI_PHY_FSM_WRITE_GO;
/* Are we going to write a command? */
if (flash_cmd_to_write) begin
flash_dq_o_r <= {{(flash_dq_width-8){1'b0}},
flash_cmd_to_write};
end
else
flash_dq_o_r <= bus_dat_i;
end
if (bus_control_state == `CFI_FSM_DO_READ) begin
flash_phy_state <= `CFI_PHY_FSM_READ_GO;
end
if (bus_control_state == `CFI_FSM_DO_RESET) begin
flash_phy_state <= `CFI_PHY_FSM_RESET_GO;
end
end
`CFI_PHY_FSM_WRITE_GO: begin
/* Assert CE, WE */
flash_we_n_r <= 1'b0;
flash_phy_state <= `CFI_PHY_FSM_WRITE_WAIT;
end
`CFI_PHY_FSM_WRITE_WAIT: begin
/* Wait for t_wlwh */
if (!flash_phy_async_wait) begin
flash_phy_state <= `CFI_PHY_FSM_WRITE_DONE;
flash_we_n_r <= 1'b1;
end
end
`CFI_PHY_FSM_WRITE_DONE: begin
flash_phy_state <= `CFI_PHY_FSM_IDLE;
end
 
`CFI_PHY_FSM_READ_GO: begin
/* Assert CE, OE */
/*flash_adv_n_r <= 1'b1;*/
flash_ce_n_r <= 1'b0;
flash_oe_n_r <= 1'b0;
flash_phy_state <= `CFI_PHY_FSM_READ_WAIT;
end
`CFI_PHY_FSM_READ_WAIT: begin
/* Wait for t_vlqv */
if (!flash_phy_async_wait) begin
flash_oe_n_r <= 1'b1;
flash_phy_state <= `CFI_PHY_FSM_READ_DONE;
end
end
`CFI_PHY_FSM_READ_DONE: begin
flash_phy_state <= `CFI_PHY_FSM_IDLE;
end
`CFI_PHY_FSM_RESET_GO: begin
flash_phy_state <= `CFI_PHY_FSM_RESET_WAIT;
flash_rst_n_r <= 1'b0;
flash_oe_n_r <= 1'b1;
end
`CFI_PHY_FSM_RESET_WAIT : begin
if (!flash_phy_async_wait) begin
flash_rst_n_r <= 1'b1;
flash_phy_state <= `CFI_PHY_FSM_RESET_DONE;
end
end
`CFI_PHY_FSM_RESET_DONE : begin
flash_phy_state <= `CFI_PHY_FSM_IDLE;
end
default:
flash_phy_state <= `CFI_PHY_FSM_IDLE;
endcase
end
 
/* Defaults are for 95ns access time part, 66MHz (15.15ns) system clock */
/* wlwh: cycles for WE assert to WE de-assert: write time */
parameter cfi_part_wlwh_cycles = 4; /* wlwh = 50ns, tck = 15ns, cycles = 4*/
/* elqv: cycles from adress to data valid */
parameter cfi_part_elqv_cycles = 7; /* tsop 256mbit elqv = 95ns, tck = 15ns, cycles = 6*/
 
assign flash_phy_async_wait = (|flash_phy_ctr);
 
/* Load counter with wait times in cycles, determined by parameters. */
always @(posedge clk)
if (rst)
flash_phy_ctr <= 0;
else if (flash_phy_state==`CFI_PHY_FSM_WRITE_GO)
flash_phy_ctr <= cfi_part_wlwh_cycles - 1;
else if (flash_phy_state==`CFI_PHY_FSM_READ_GO)
flash_phy_ctr <= cfi_part_elqv_cycles - 2;
else if (flash_phy_state==`CFI_PHY_FSM_RESET_GO)
flash_phy_ctr <= 10;
else if (|flash_phy_ctr)
flash_phy_ctr <= flash_phy_ctr - 1;
 
/* Signal to indicate when we should drive the data bus */
wire flash_bus_write_enable;
assign flash_bus_write_enable = (bus_control_state == `CFI_FSM_DO_WRITE) |
(bus_control_state == `CFI_FSM_DO_WRITE_WAIT);
/* Assign signals to physical bus */
assign flash_dq_io = flash_bus_write_enable ? flash_dq_o_r :
{flash_dq_width{1'bz}};
assign flash_adr_o = flash_adr_r;
assign flash_adv_n_o = flash_adv_n_r;
assign flash_wp_n_o = 1'b1; /* Never write protect */
assign flash_ce_n_o = flash_ce_n_r;
assign flash_oe_n_o = flash_oe_n_r;
assign flash_we_n_o = flash_we_n_r;
assign flash_clk_o = 1'b1;
assign flash_rst_n_o = flash_rst_n_r;
endmodule // cfi_ctrl_engine
 
 
/verilog/ram_wb/ram_wb_b3.v
1,3 → 1,4
//`include "synthesis-defines.v"
module ram_wb_b3(
wb_adr_i, wb_bte_i, wb_cti_i, wb_cyc_i, wb_dat_i, wb_sel_i,
wb_stb_i, wb_we_i,
119,7 → 120,7
If not Verilator model, always do load, otherwise only load when called
from SystemC testbench.
*/
 
// synthesis translate_off
parameter memory_file = "sram.vmem";
 
`ifdef verilator
135,9 → 136,11
begin
$readmemh(memory_file, mem);
end
 
`endif // !`ifdef verilator
`endif // !`ifdef verilator
 
//synthesis translate_on
assign wb_rty_o = 0;
 
// mux for data to ram, RMW on part sel != 4'hf
209,9 → 212,9
// Error signal generation
//
// Error when out of bounds of memory - skip top byte of address in case
// this is mapped somewhere other than 0x00.
assign addr_err = wb_cyc_i & wb_stb_i & (|wb_adr_i[aw-1-8:mem_adr_width]);
// Error when out of bounds of memory - skip top nibble of address in case
// this is mapped somewhere other than 0x0.
assign addr_err = wb_cyc_i & wb_stb_i & (|wb_adr_i[aw-1-4:mem_adr_width]);
// OR in other errors here...
assign wb_err_o = wb_ack_o_r & wb_stb_i &

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.