mirror of
				https://github.com/marqs85/ossc
				synced 2025-10-31 16:06:02 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			612 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Systemverilog
		
	
	
	
	
	
			
		
		
	
	
			612 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Systemverilog
		
	
	
	
	
	
| // (C) 2001-2015 Altera Corporation. All rights reserved.
 | |
| // Your use of Altera Corporation's design tools, logic functions and other 
 | |
| // software and tools, and its AMPP partner logic functions, and any output 
 | |
| // files any of the foregoing (including device programming or simulation 
 | |
| // files), and any associated documentation or information are expressly subject 
 | |
| // to the terms and conditions of the Altera Program License Subscription 
 | |
| // Agreement, Altera MegaCore Function License Agreement, or other applicable 
 | |
| // license agreement, including, without limitation, that your use is for the 
 | |
| // sole purpose of programming logic devices manufactured by Altera and sold by 
 | |
| // Altera or its authorized distributors.  Please refer to the applicable 
 | |
| // agreement for further details.
 | |
| 
 | |
| 
 | |
| // (C) 2001-2015 Altera Corporation. All rights reserved.
 | |
| // Your use of Altera Corporation's design tools, logic functions and other 
 | |
| // software and tools, and its AMPP partner logic functions, and any output 
 | |
| // files any of the foregoing (including device programming or simulation 
 | |
| // files), and any associated documentation or information are expressly subject 
 | |
| // to the terms and conditions of the Altera Program License Subscription 
 | |
| // Agreement, Altera MegaCore Function License Agreement, or other applicable 
 | |
| // license agreement, including, without limitation, that your use is for the 
 | |
| // sole purpose of programming logic devices manufactured by Altera and sold by 
 | |
| // Altera or its authorized distributors.  Please refer to the applicable 
 | |
| // agreement for further details.
 | |
| 
 | |
| 
 | |
| 
 | |
| `timescale 1ps / 1ps
 | |
| 
 | |
| module altera_epcq_controller #(
 | |
| 	parameter CS_WIDTH		= 1,
 | |
| 	parameter ENABLE_4BYTE_ADDR = 1,
 | |
| 	parameter ADDR_WIDTH	= 22,
 | |
| 	parameter ASI_WIDTH		= 1,
 | |
| 	parameter DEVICE_FAMILY = "CYCLONE V",
 | |
| 	parameter ASMI_ADDR_WIDTH = 22,
 | |
| 	parameter CHIP_SELS = 1
 | |
| )(
 | |
| 	input 	wire		  								clk,
 | |
| 	input 	wire		  								reset_n,
 | |
| 	                                        			
 | |
| 	// ports to access csr                        			
 | |
| 	input 	wire										avl_csr_write,
 | |
| 	input 	wire		  								avl_csr_read,
 | |
| 	input 	wire 	[2:0] 								avl_csr_addr,
 | |
| 	input 	wire 	[31:0] 								avl_csr_wrdata,
 | |
| 	output 	reg 	[31:0] 								avl_csr_rddata,
 | |
| 	output 	reg 		 								avl_csr_rddata_valid,
 | |
| 	output 	reg 			 							avl_csr_waitrequest,
 | |
| 	                                        			
 | |
| 	// ports to access memory        			
 | |
| 	input	wire		  								avl_mem_write,
 | |
| 	input	wire										avl_mem_read,
 | |
| 	input	wire  	[ADDR_WIDTH-1:0]					avl_mem_addr,			
 | |
| 	input	wire	[31:0]								avl_mem_wrdata,
 | |
| 	input	wire 	[3:0]								avl_mem_byteenable,
 | |
| 	input	wire	[6:0]								avl_mem_burstcount,
 | |
| 	output	wire	[31:0]								avl_mem_rddata,
 | |
| 	output	reg											avl_mem_rddata_valid,
 | |
| 	output 	reg 			 							avl_mem_waitrequest,
 | |
| 	
 | |
| 	// interrupt signal
 | |
| 	output	reg 										irq,
 | |
| 	
 | |
| 	// Disable dedicated active serial interface
 | |
| 	input  	wire	[ASI_WIDTH-1:0]						epcq_dataout,
 | |
| 	output  reg											epcq_dclk,
 | |
| 	output  reg		[CS_WIDTH-1:0] 						epcq_scein,
 | |
| 	output  reg		[ASI_WIDTH-1:0]						epcq_sdoin,
 | |
| 	output  reg		[ASI_WIDTH-1:0]						epcq_dataoe,
 | |
| 	
 | |
| 	// ASMI PARALLEL interface
 | |
| 	input   wire	[ASI_WIDTH-1:0]						ddasi_dataoe,
 | |
| 	output  reg 	[ASI_WIDTH-1:0]						ddasi_dataout,
 | |
| 	input   wire 										ddasi_dclk,
 | |
| 	input   wire 	[CS_WIDTH-1:0] 						ddasi_scein,
 | |
| 	input   reg		[ASI_WIDTH-1:0]  					ddasi_sdoin,
 | |
| 	
 | |
| 	input   wire										asmi_busy,
 | |
| 	input   wire										asmi_data_valid,
 | |
| 	input   wire	[7:0]  								asmi_dataout,
 | |
| 	output  reg											asmi_clkin,
 | |
| 	output  reg											asmi_reset,
 | |
| 	output  reg		[CS_WIDTH-1:0] 						asmi_sce,
 | |
| 	output	reg	    [ASMI_ADDR_WIDTH-1:0]  				asmi_addr,
 | |
| 	output  reg		[7:0]  								asmi_datain,
 | |
| 	output  reg											asmi_fast_read,
 | |
| 	output  wire										asmi_rden,
 | |
| 	output  reg											asmi_shift_bytes,
 | |
| 	output  reg 										asmi_en4b_addr,
 | |
| 	output  wire										asmi_wren,
 | |
| 	output  reg											asmi_write,
 | |
| 	
 | |
| 	input   wire										asmi_illegal_erase,
 | |
| 	input   wire										asmi_illegal_write,
 | |
| 	input   wire	[7:0]  								asmi_rdid_out,
 | |
| 	input   wire	[7:0]  								asmi_status_out,
 | |
| 	input   wire	[7:0]  								asmi_epcs_id,
 | |
| 	output  reg											asmi_read_rdid,
 | |
| 	output  reg											asmi_read_status,
 | |
| 	output	reg											asmi_read_sid,
 | |
| 	output  reg 										asmi_bulk_erase,
 | |
| 	output  reg											asmi_sector_erase,
 | |
| 	output  reg											asmi_sector_protect
 | |
| );
 | |
| 	localparam LOCAL_ADDR_WIDTH = ADDR_WIDTH+2;
 | |
| 	localparam CSR_DATA_WIDTH   = 32;
 | |
| 	localparam LAST_ADDR_BIT    = (ASMI_ADDR_WIDTH == 24) ? 15 :
 | |
| 									(ASMI_ADDR_WIDTH == 32) ? 23 : 15;
 | |
| 	
 | |
| 	reg  [8:0] wr_burstcount_cnt, rd_burstcount_cnt;
 | |
| 	reg	 [8:0] rd_mem_burstcount, wr_mem_burstcount;
 | |
| 	
 | |
| 	wire last_wr_byte;
 | |
| 	wire access_csr_status, access_csr_sid, access_csr_rdid, access_csr_mem_op, access_isr, access_imr, access_sce;
 | |
| 	wire read_status_combi, read_sid_combi, read_rdid_combi, read_isr_combi, read_imr_combi, write_isr_combi, write_imr_combi, write_sce_combi;
 | |
| 	wire bulk_erase_combi, sector_erase_combi, sector_protect_combi;
 | |
| 	wire wren_combi, illegal_write_combi, illegal_erase_combi;
 | |
| 	wire m_illegal_write_combi, m_illegal_erase_combi;
 | |
| 	wire read_mem_combi, write_mem_combi;
 | |
| 	wire data_valid_combi, pending_wr_data;
 | |
| 	wire detect_addroffset;
 | |
| 	wire [8:0] wfifo_data_in_0, wfifo_data_in_1, wfifo_data_in_2, wfifo_data_in_3;
 | |
| 	wire [ADDR_WIDTH-1:0] temp_mem_addr;
 | |
| 	
 | |
| 	reg reset_n_reg;
 | |
| 	reg wr_mem_waitrequest, local_waitrequest;
 | |
| 	reg illegal_write_reg, illegal_erase_reg, m_illegal_write_reg, m_illegal_erase_reg;
 | |
| 	reg read_status_valid, read_sid_valid, read_rdid_valid, read_isr_valid, read_imr_valid;
 | |
| 	reg read_status_en, read_sid_en, read_rdid_en;
 | |
| 	reg wren_internal;
 | |
| 	reg [LOCAL_ADDR_WIDTH-1:0] wr_mem_addr;
 | |
| 	reg [7:0] rd_data_reg [4];
 | |
| 	reg [3:0][8:0] wr_data_reg;
 | |
| 	reg [1:0] rd_cnt;
 | |
| 	reg [1:0] wr_cnt;
 | |
| 	reg [3:0] wr_data_reg_full;
 | |
| 	reg detect_addroffset_reg, asmi_busy_reg;
 | |
| 	reg [2:0] temp_sce;
 | |
| 	
 | |
| 	// Direct connection
 | |
| 	assign asmi_clkin 		= clk;
 | |
| 	assign asmi_reset 		= ~reset_n;
 | |
| 	assign ddasi_dataout 	= epcq_dataout;
 | |
| 	assign epcq_dclk 		= ddasi_dclk;
 | |
| 	assign epcq_scein		= ddasi_scein;
 | |
| 	assign epcq_sdoin		= ddasi_sdoin;
 | |
| 	assign epcq_dataoe		= ddasi_dataoe;
 | |
| 	
 | |
| 	// chip select
 | |
| 	generate if (DEVICE_FAMILY == "Arria 10") begin
 | |
| 		always @(posedge clk or negedge reset_n) begin
 | |
| 			if (~reset_n) begin
 | |
| 				asmi_sce			<= {CS_WIDTH{1'b0}};
 | |
| 			end 
 | |
| // to pack the address space this is needed
 | |
| 			else if (write_mem_combi || read_mem_combi) begin
 | |
| 				if (CHIP_SELS == 1 ) 					
 | |
| 					asmi_sce			<= 3'b001;
 | |
| 				else if (CHIP_SELS == 2 && avl_mem_addr[ADDR_WIDTH-1] == 0) 
 | |
| 					asmi_sce			<= 3'b001;
 | |
| 				else if (CHIP_SELS == 2 && avl_mem_addr[ADDR_WIDTH-1] == 1) 
 | |
| 					asmi_sce			<= 3'b010;
 | |
| 				else if (CHIP_SELS == 3 && avl_mem_addr[ADDR_WIDTH-1] == 1)	
 | |
| 					asmi_sce			<= 3'b100;
 | |
| 				else if (CHIP_SELS == 3 && avl_mem_addr[ADDR_WIDTH-1:ADDR_WIDTH-2] == 0) 	
 | |
| 					asmi_sce			<= 3'b001;
 | |
| 				else if (CHIP_SELS == 3 && avl_mem_addr[ADDR_WIDTH-1:ADDR_WIDTH-2] == 1) 	
 | |
| 					asmi_sce			<= 3'b010;
 | |
| 				else
 | |
| 					asmi_sce			<= {CS_WIDTH{1'b0}};
 | |
| 			end
 | |
| 			else if (write_sce_combi) begin
 | |
| 				asmi_sce			<= avl_csr_wrdata[2:0];
 | |
| 			end
 | |
| 			else if (asmi_en4b_addr) begin
 | |
| 				asmi_sce			<= temp_sce;
 | |
| 			end
 | |
| 		end
 | |
| // decoder ring  if the CHIP_SEL is only 1 then avalon address is the temp address
 | |
| //		if the chipsele is 2 then need to remove top address bit
 | |
| //		if the chipelect is 3 then remove the top 2 address bits.  
 | |
| 		assign temp_mem_addr	= CHIP_SELS == 1 ? avl_mem_addr:( CHIP_SELS == 2 ? {1'b0,avl_mem_addr[ADDR_WIDTH-2:0]}:{2'b00,avl_mem_addr[ADDR_WIDTH-3:0]});
 | |
| 	end
 | |
| 	else begin
 | |
| 		always @(posedge clk) begin
 | |
| 			asmi_sce				<= {CS_WIDTH{1'b0}};
 | |
| 		end
 | |
| 		assign temp_mem_addr	= avl_mem_addr;
 | |
| 	end
 | |
| 	endgenerate
 | |
| 	
 | |
| 	// wait_request generation logic
 | |
| 	assign avl_mem_waitrequest = (asmi_busy || asmi_busy_reg) ? 1'b1 : (local_waitrequest || wr_mem_waitrequest);
 | |
| 	assign avl_csr_waitrequest = (asmi_busy || asmi_busy_reg) ? 1'b1 : (local_waitrequest || wr_mem_waitrequest);
 | |
| 	
 | |
| 	// access CSR decoding logic
 | |
| 	assign access_csr_status	= (avl_csr_addr == 3'b000);
 | |
| 	assign access_csr_sid		= (avl_csr_addr == 3'b001);
 | |
| 	assign access_csr_rdid		= (avl_csr_addr == 3'b010);
 | |
| 	assign access_csr_mem_op	= (avl_csr_addr == 3'b011);
 | |
| 	assign access_isr			= (avl_csr_addr == 3'b100);
 | |
| 	assign access_imr			= (avl_csr_addr == 3'b101);
 | |
| 	assign access_sce			= (avl_csr_addr == 3'b110);
 | |
| 	
 | |
| 	// read/write memory combi logic
 | |
| 	assign read_mem_combi		= (avl_mem_read && ~avl_mem_waitrequest);
 | |
| 	assign write_mem_combi		= (avl_mem_write && ~avl_mem_waitrequest);
 | |
| 
 | |
| 	// read csr logic
 | |
| 	assign read_status_combi	= (avl_csr_read && access_csr_status && ~avl_csr_waitrequest);
 | |
| 	assign read_sid_combi		= (avl_csr_read && access_csr_sid && ~avl_csr_waitrequest);
 | |
| 	assign read_rdid_combi		= (avl_csr_read && access_csr_rdid && ~avl_csr_waitrequest);
 | |
| 	assign read_isr_combi		= (avl_csr_read && access_isr && ~avl_csr_waitrequest);
 | |
| 	assign read_imr_combi		= (avl_csr_read && access_imr && ~avl_csr_waitrequest);
 | |
| 	assign write_isr_combi		= (avl_csr_write && access_isr && ~avl_csr_waitrequest);
 | |
| 	assign write_imr_combi		= (avl_csr_write && access_imr && ~avl_csr_waitrequest);
 | |
| 	assign write_sce_combi		= (avl_csr_write && access_sce && ~avl_csr_waitrequest);
 | |
| 	
 | |
| 	// write csr logic
 | |
| 	assign bulk_erase_combi		= (avl_csr_write && access_csr_mem_op && ~avl_csr_waitrequest && avl_csr_wrdata[1:0] == 2'b01);
 | |
| 	assign sector_erase_combi	= (avl_csr_write && access_csr_mem_op && ~avl_csr_waitrequest && avl_csr_wrdata[1:0] == 2'b10);
 | |
| 	assign sector_protect_combi	= (avl_csr_write && access_csr_mem_op && ~avl_csr_waitrequest && avl_csr_wrdata[1:0] == 2'b11);
 | |
| 	assign illegal_write_combi	= (asmi_illegal_write) ? 1'b1 :
 | |
| 									(write_isr_combi && avl_csr_wrdata[1]) ? 1'b0 : 
 | |
| 										illegal_write_reg;
 | |
| 	assign illegal_erase_combi	= (asmi_illegal_erase) ? 1'b1 :
 | |
| 									(write_isr_combi && avl_csr_wrdata[0]) ? 1'b0 : 
 | |
| 										illegal_erase_reg;
 | |
| 	assign m_illegal_write_combi= (write_imr_combi) ? avl_csr_wrdata[1] : m_illegal_write_reg;
 | |
| 	assign m_illegal_erase_combi= (write_imr_combi) ? avl_csr_wrdata[0] : m_illegal_erase_reg;
 | |
| 	assign wren_combi			= (sector_protect_combi || sector_erase_combi || bulk_erase_combi);
 | |
| 										
 | |
| 	assign asmi_rden			= (rd_burstcount_cnt > 9'd0);		// deasserted at the last 2 byte - refer to ASMI_PARALLEL UG
 | |
| 
 | |
| 	// interrupt signal
 | |
| 	assign irq = (illegal_write_reg && m_illegal_write_reg) || (illegal_erase_reg && m_illegal_erase_reg);
 | |
| 	
 | |
| 	assign last_wr_byte = (wr_burstcount_cnt == wr_mem_burstcount - 9'd1) ? 1'b1 : 1'b0;
 | |
| 	
 | |
| 	assign asmi_wren = wren_internal || asmi_en4b_addr || asmi_shift_bytes || asmi_write;
 | |
| 	
 | |
| 	assign data_valid_combi = (rd_burstcount_cnt[1:0] == 2'b00) ? asmi_data_valid : 1'b0;
 | |
| 	
 | |
| 	assign wfifo_data_in_0 = {avl_mem_byteenable[0], avl_mem_wrdata[7:0]   };
 | |
| 	assign wfifo_data_in_1 = {avl_mem_byteenable[1], avl_mem_wrdata[15:8]  };
 | |
| 	assign wfifo_data_in_2 = {avl_mem_byteenable[2], avl_mem_wrdata[23:16] };
 | |
| 	assign wfifo_data_in_3 = {avl_mem_byteenable[3], avl_mem_wrdata[31:24] };
 | |
| 	
 | |
| 	assign avl_mem_rddata  = {rd_data_reg[3], rd_data_reg[2], rd_data_reg[1], rd_data_reg[0]};
 | |
| 	assign pending_wr_data = (|wr_data_reg_full) ? 1'b1 : 1'b0;
 | |
| 	assign detect_addroffset = (pending_wr_data && wr_data_reg[wr_cnt][8]) ? 1'b1 : 
 | |
| 								(wr_burstcount_cnt == {9{1'b0}}) ? 1'b0 : detect_addroffset_reg;
 | |
| 
 | |
| 	//-------------------------------- array to store write data -------------------------------------
 | |
| 	always @(posedge clk or negedge reset_n) begin
 | |
| 		if (~reset_n) begin
 | |
| 			wr_data_reg			<= '{{9{1'b0}}, {9{1'b0}}, {9{1'b0}}, {9{1'b0}}};
 | |
| 			wr_data_reg_full	<= {4{1'b0}};
 | |
| 		end 
 | |
| 		else if (write_mem_combi) begin
 | |
| 			wr_data_reg			<= {wfifo_data_in_3, wfifo_data_in_2, wfifo_data_in_1, wfifo_data_in_0};
 | |
| 			wr_data_reg_full	<= {4{1'b1}};
 | |
| 		end
 | |
| 		else if (wr_data_reg_full > 4'b0000) begin
 | |
| 			wr_data_reg_full	<= wr_data_reg_full << 1;
 | |
| 		end
 | |
| 	end
 | |
| 	
 | |
| 	//-------------------------------- array to store read data -------------------------------------
 | |
| 	always @(posedge clk or negedge reset_n) begin
 | |
| 		if (~reset_n) begin
 | |
| 			rd_data_reg			<= '{{8{1'b0}}, {8{1'b0}}, {8{1'b0}}, {8{1'b0}}};
 | |
| 			rd_cnt				<= {2{1'b0}};
 | |
| 		end 
 | |
| 		else if (asmi_data_valid) begin
 | |
| 			rd_data_reg[rd_cnt]	<= asmi_dataout;
 | |
| 			rd_cnt				<= rd_cnt + 2'b01;
 | |
| 		end
 | |
| 	end
 | |
| 	
 | |
| 	//------------------------------- Enable 4-byte addressing out of reset ----------------------
 | |
| 	generate 
 | |
| 	if (ENABLE_4BYTE_ADDR) begin
 | |
| 		typedef enum logic[1:0] {EN4B_CHIP1, EN4B_CHIP2, EN4B_CHIP3, IDLE} state_t;
 | |
| 		state_t state;
 | |
| 	
 | |
| 		always @(posedge clk or negedge reset_n_reg) begin	// use reset_n_reg because user is allow to send cmd to ASMI_PARALLEL 2 clock cycles after reset
 | |
| 			if (~reset_n_reg) begin	
 | |
| 				state					<= EN4B_CHIP1;
 | |
| 				asmi_en4b_addr			<= 1'b1;
 | |
| 				temp_sce				<= 3'b001;
 | |
| 			end
 | |
| 			else begin
 | |
| 				case (state)
 | |
| 					EN4B_CHIP1 : begin
 | |
| 									asmi_en4b_addr			<= 1'b1;
 | |
| 									if (~asmi_busy) begin
 | |
| 										if (CHIP_SELS > 1) begin
 | |
| 											state					<= EN4B_CHIP2;
 | |
| 											temp_sce				<= 3'b010;
 | |
| 										end
 | |
| 										else begin
 | |
| 											state					<= IDLE;
 | |
| 											temp_sce				<= 3'b000;
 | |
| 										end
 | |
| 									end
 | |
| 								 end
 | |
| 					EN4B_CHIP2 : begin
 | |
| 									asmi_en4b_addr			<= 1'b1;
 | |
| 									if (~asmi_busy) begin
 | |
| 										if (CHIP_SELS > 2) begin
 | |
| 											state					<= EN4B_CHIP3;
 | |
| 											temp_sce				<= 3'b100;
 | |
| 										end
 | |
| 										else begin
 | |
| 											state					<= IDLE;
 | |
| 											temp_sce				<= 3'b000;
 | |
| 										end
 | |
| 									end
 | |
| 								 end
 | |
| 					EN4B_CHIP3 : begin
 | |
| 									asmi_en4b_addr			<= 1'b1;
 | |
| 									if (~asmi_busy) begin
 | |
| 										state					<= IDLE;
 | |
| 										temp_sce				<= 3'b000;
 | |
| 									end
 | |
| 								 end
 | |
| 					IDLE	   : begin
 | |
| 									asmi_en4b_addr			<= 1'b0;
 | |
| 									state					<= IDLE;
 | |
| 									temp_sce				<= 3'b000;
 | |
| 								 end
 | |
| 					default : 	 begin
 | |
| 									asmi_en4b_addr			<= 1'b0;
 | |
| 									state					<= IDLE;
 | |
| 									temp_sce				<= 3'b000;
 | |
| 								 end
 | |
| 				endcase
 | |
| 			end
 | |
| 		end
 | |
| 	end
 | |
| 	else begin
 | |
| 		always @(posedge clk) begin
 | |
| 			asmi_en4b_addr				<= 1'b0;
 | |
| 			temp_sce					<= 3'b000;
 | |
| 		end
 | |
| 	end
 | |
| 	endgenerate
 | |
| 	
 | |
| 	//--------------------------------------- Waitrequest logic ----------------------------------
 | |
| 	always @(posedge clk or negedge reset_n) begin
 | |
| 		if (~reset_n) begin
 | |
| 			wr_mem_waitrequest			<= 1'b0;
 | |
| 			local_waitrequest			<= 1'b0;
 | |
| 		end
 | |
| 		else begin
 | |
| 			if (read_mem_combi || read_status_combi || read_sid_combi || read_rdid_combi || bulk_erase_combi || sector_erase_combi || sector_protect_combi || asmi_en4b_addr) begin		// no back pressure during imr & isr access
 | |
| 				local_waitrequest		<= 1'b1;
 | |
| 			end
 | |
| 			else if (asmi_busy_reg && ~asmi_busy) begin
 | |
| 				local_waitrequest		<= 1'b0;
 | |
| 			end
 | |
| 			
 | |
| 			if (write_mem_combi) begin
 | |
| 				wr_mem_waitrequest	<= 1'b1;
 | |
| 			end
 | |
| 			else if ((~pending_wr_data && ~asmi_write) || asmi_busy_reg && ~asmi_busy) begin
 | |
| 				wr_mem_waitrequest	<= 1'b0;
 | |
| 			end
 | |
| 		end
 | |
| 	end
 | |
| 	
 | |
| 	// -------------------------------------- MEM ACCESS -----------------------------------------
 | |
| 	always @(posedge clk or negedge reset_n) begin
 | |
| 		if (~reset_n) begin
 | |
| 			rd_mem_burstcount			<= {9{1'b0}};
 | |
| 			wr_mem_burstcount			<= {9{1'b0}};
 | |
| 			wr_mem_addr					<= {LOCAL_ADDR_WIDTH{1'b0}};
 | |
| 		end
 | |
| 		else begin
 | |
| 			if (read_mem_combi) begin
 | |
| 				rd_mem_burstcount		<= {avl_mem_burstcount, 2'b00}; 
 | |
| 			end
 | |
| 			if (write_mem_combi && (wr_burstcount_cnt == {9{1'b0}})) begin
 | |
| 				wr_mem_addr				<= {temp_mem_addr, 2'b00};
 | |
| 				wr_mem_burstcount		<= {avl_mem_burstcount, 2'b00}; 
 | |
| 			end
 | |
| 		end
 | |
| 	end
 | |
| 	
 | |
| 	always @(posedge clk or negedge reset_n) begin
 | |
| 		if (~reset_n) begin
 | |
| 			wr_burstcount_cnt				<= {9{1'b0}};
 | |
| 		end
 | |
| 		else begin
 | |
| 			if (pending_wr_data) begin
 | |
| 				wr_burstcount_cnt			<= wr_burstcount_cnt + 9'd1;
 | |
| 			end
 | |
| 			else if (wr_burstcount_cnt == wr_mem_burstcount) begin
 | |
| 				wr_burstcount_cnt			<= {9{1'b0}};
 | |
| 			end
 | |
| 		end
 | |
| 	end
 | |
| 	
 | |
| 	always @(posedge clk or negedge reset_n) begin
 | |
| 		if (~reset_n) begin
 | |
| 			rd_burstcount_cnt				<= {9{1'b0}};
 | |
| 		end
 | |
| 		else begin
 | |
| 			if (read_mem_combi) begin
 | |
| 				rd_burstcount_cnt			<= 9'd1;
 | |
| 			end
 | |
| 			else if (rd_burstcount_cnt == rd_mem_burstcount) begin		// each rd 4 burst
 | |
| 				rd_burstcount_cnt			<= {9{1'b0}};
 | |
| 			end
 | |
| 			else if (asmi_data_valid && rd_burstcount_cnt > 0) begin
 | |
| 				rd_burstcount_cnt			<= rd_burstcount_cnt + 9'd1;
 | |
| 			end
 | |
| 		end
 | |
| 	end
 | |
| 	
 | |
| 	always @(posedge clk or negedge reset_n) begin
 | |
| 		if (~reset_n) begin
 | |
| 			asmi_addr					<= {ASMI_ADDR_WIDTH{1'b0}};
 | |
| 		end
 | |
| 		else begin
 | |
| 			if (sector_erase_combi) begin // set lower 16 bits to zero so that erase at starting address of each sector
 | |
| 				asmi_addr				<= {avl_csr_wrdata[LAST_ADDR_BIT : 8], {16{1'b0}}};	
 | |
| 			end
 | |
| 			if (read_mem_combi) begin
 | |
| 				asmi_addr				<= {temp_mem_addr, 2'b00};
 | |
| 			end
 | |
| 			
 | |
| 			if (detect_addroffset && ~detect_addroffset_reg) begin
 | |
| 				asmi_addr			<= wr_mem_addr + {{LOCAL_ADDR_WIDTH-9{1'b0}}, wr_burstcount_cnt};
 | |
| 			end
 | |
| 
 | |
| 		end
 | |
| 	end
 | |
| 	
 | |
| 	always @(posedge clk or negedge reset_n) begin
 | |
| 		if (~reset_n) begin
 | |
| 			asmi_datain					<= {8{1'b0}};
 | |
| 			wr_cnt						<= {2{1'b0}};
 | |
| 			asmi_shift_bytes			<= 1'b0;
 | |
| 		end
 | |
| 		else begin
 | |
| 			if (sector_protect_combi) begin
 | |
| 				asmi_datain				<= {{1{1'b0}}, avl_csr_wrdata[11], avl_csr_wrdata[12], avl_csr_wrdata[10:8], {2{1'b0}}};	// BP3, TB, BP2, BP1, BP0
 | |
| 			end
 | |
| 			if (pending_wr_data) begin
 | |
| 				asmi_datain				<= wr_data_reg[wr_cnt][7:0];
 | |
| 				wr_cnt					<= wr_cnt + 2'd1;
 | |
| 			end
 | |
| 			if (pending_wr_data && wr_data_reg[wr_cnt][8]) begin
 | |
| 				asmi_shift_bytes		<= 1'b1;
 | |
| 			end
 | |
| 			else begin
 | |
| 				asmi_shift_bytes		<= 1'b0;
 | |
| 			end
 | |
| 		end
 | |
| 	end
 | |
| 	
 | |
| 	always @(posedge clk or negedge reset_n) begin
 | |
| 		if (~reset_n) begin
 | |
| 			asmi_read_status			<= 1'b0;
 | |
| 			asmi_read_sid				<= 1'b0;
 | |
| 			asmi_read_rdid				<= 1'b0;
 | |
| 			asmi_bulk_erase				<= 1'b0;
 | |
| 			asmi_sector_erase			<= 1'b0;
 | |
| 			asmi_sector_protect			<= 1'b0;
 | |
| 			wren_internal				<= 1'b0;
 | |
| 			asmi_write					<= 1'b0;
 | |
| 			asmi_fast_read				<= 1'b0;
 | |
| 			asmi_busy_reg				<= 1'b0;
 | |
| 			avl_mem_rddata_valid		<= 1'b0;
 | |
| 			detect_addroffset_reg		<= 1'b0;
 | |
| 			reset_n_reg					<= 1'b0;
 | |
| 		end
 | |
| 		else begin
 | |
| 			asmi_read_status			<= read_status_combi;
 | |
| 			asmi_read_sid				<= read_sid_combi;
 | |
| 			asmi_read_rdid				<= read_rdid_combi;
 | |
| 			asmi_bulk_erase				<= bulk_erase_combi;
 | |
| 			asmi_sector_erase			<= sector_erase_combi;				
 | |
| 			asmi_sector_protect			<= sector_protect_combi;
 | |
| 			wren_internal				<= wren_combi;
 | |
| 			asmi_write					<= last_wr_byte;
 | |
| 			asmi_fast_read				<= read_mem_combi;
 | |
| 			asmi_busy_reg				<= asmi_busy;
 | |
| 			avl_mem_rddata_valid		<= data_valid_combi;
 | |
| 			detect_addroffset_reg		<= detect_addroffset;
 | |
| 			reset_n_reg					<= 1'b1;
 | |
| 		end
 | |
| 	end
 | |
| 	
 | |
| 	// --------------------------------------------- CSR ACCESS -------------------------------------
 | |
| 	always @(posedge clk or negedge reset_n) begin
 | |
| 		if (~reset_n) begin
 | |
| 			illegal_write_reg			<= 1'b0;
 | |
| 			illegal_erase_reg			<= 1'b0;
 | |
| 			m_illegal_write_reg			<= 1'b0;
 | |
| 			m_illegal_erase_reg			<= 1'b0;
 | |
| 		end
 | |
| 		else begin
 | |
| 			illegal_write_reg			<= illegal_write_combi;
 | |
| 			illegal_erase_reg			<= illegal_erase_combi;
 | |
| 			m_illegal_write_reg			<= m_illegal_write_combi;
 | |
| 			m_illegal_erase_reg			<= m_illegal_erase_combi;
 | |
| 		end
 | |
| 	end
 | |
| 	
 | |
| 	// csr read only registers enable logic
 | |
| 	always @(posedge clk or negedge reset_n) begin
 | |
| 		if (~reset_n) begin
 | |
| 			read_status_en				<= 1'b0;
 | |
| 			read_sid_en 				<= 1'b0;
 | |
| 			read_rdid_en				<= 1'b0;
 | |
| 		end
 | |
| 		else if (asmi_read_status) begin
 | |
| 			read_status_en				<= 1'b1;
 | |
| 		end
 | |
| 		else if (asmi_read_sid) begin
 | |
| 			read_sid_en					<= 1'b1;
 | |
| 		end
 | |
| 		else if (asmi_read_rdid) begin
 | |
| 			read_rdid_en				<= 1'b1;
 | |
| 		end
 | |
| 		else if (asmi_busy == 0) begin
 | |
| 			read_status_en				<= 1'b0;
 | |
| 			read_sid_en 				<= 1'b0;
 | |
| 			read_rdid_en				<= 1'b0;
 | |
| 		end
 | |
| 	end
 | |
| 	
 | |
| 	// generation logic for avl csr read data valid
 | |
| 	assign avl_csr_rddata_valid	= read_status_valid || read_sid_valid || read_rdid_valid || read_isr_valid || read_imr_valid;
 | |
| 	
 | |
| 	always @(posedge clk or negedge reset_n) begin
 | |
| 		if (~reset_n) begin
 | |
| 			read_status_valid			<= 1'b0;
 | |
| 			read_sid_valid				<= 1'b0;
 | |
| 			read_rdid_valid				<= 1'b0;
 | |
| 			read_isr_valid				<= 1'b0;
 | |
| 			read_imr_valid				<= 1'b0;
 | |
| 		end
 | |
| 		else begin
 | |
| 			if (read_status_en && asmi_busy == 0) begin
 | |
| 				read_status_valid			<= 1'b1;
 | |
| 			end
 | |
| 			else begin
 | |
| 				read_status_valid			<= 1'b0;
 | |
| 			end
 | |
| 			
 | |
| 			if (read_sid_en && asmi_busy == 0) begin
 | |
| 				read_sid_valid				<= 1'b1;
 | |
| 			end
 | |
| 			else begin
 | |
| 				read_sid_valid				<= 1'b0;
 | |
| 			end
 | |
| 			
 | |
| 			if (read_rdid_en && asmi_busy == 0) begin
 | |
| 				read_rdid_valid				<= 1'b1;
 | |
| 			end
 | |
| 			else begin
 | |
| 				read_rdid_valid				<= 1'b0;
 | |
| 			end
 | |
| 			
 | |
| 			if (read_isr_combi) begin
 | |
| 				read_isr_valid				<= 1'b1;
 | |
| 			end
 | |
| 			else begin
 | |
| 				read_isr_valid				<= 1'b0;
 | |
| 			end
 | |
| 			
 | |
| 			if (read_imr_combi) begin
 | |
| 				read_imr_valid				<= 1'b1;
 | |
| 			end
 | |
| 			else begin
 | |
| 				read_imr_valid				<= 1'b0;
 | |
| 			end
 | |
| 		end
 | |
| 	end
 | |
| 	
 | |
| 	// generation logic for avl csr read data
 | |
| 	always @(posedge clk or negedge reset_n) begin
 | |
| 		if (~reset_n) begin
 | |
| 			avl_csr_rddata				<= {CSR_DATA_WIDTH{1'b0}};
 | |
| 		end
 | |
| 		else begin
 | |
| 			if (read_status_en && asmi_busy == 0) begin
 | |
| 				avl_csr_rddata				<= {{CSR_DATA_WIDTH-8{1'b0}}, asmi_status_out};
 | |
| 			end
 | |
| 			if (read_sid_en && asmi_busy == 0) begin
 | |
| 				avl_csr_rddata				<= {{CSR_DATA_WIDTH-8{1'b0}}, asmi_epcs_id};
 | |
| 			end
 | |
| 			if (read_rdid_en && asmi_busy == 0) begin
 | |
| 				avl_csr_rddata				<= {{CSR_DATA_WIDTH-8{1'b0}}, asmi_rdid_out};
 | |
| 			end
 | |
| 			if (read_isr_combi) begin
 | |
| 				avl_csr_rddata				<= {{CSR_DATA_WIDTH-2{1'b0}}, illegal_write_reg, illegal_erase_reg};
 | |
| 			end
 | |
| 			if (read_imr_combi) begin
 | |
| 				avl_csr_rddata				<= {{CSR_DATA_WIDTH-2{1'b0}}, m_illegal_write_reg, m_illegal_erase_reg};
 | |
| 			end
 | |
| 		end
 | |
| 	end
 | |
| 	
 | |
| 
 | |
| endmodule
 | 
