1495 lines
37 KiB
Verilog
1495 lines
37 KiB
Verilog
////////////////////////////////////////////////////////////////////////////
|
|
// _____
|
|
// / _______ Copyright (C) 2013-2022 Efinix Inc. All rights reserved.
|
|
// / / \
|
|
// / / .. / design_modules.v
|
|
// / / .' /
|
|
// __/ /.' / Description:
|
|
// __ \ / Modules for SapphireSoC example design
|
|
// /_/ /\ \_____/ /
|
|
// ____/ \_______/
|
|
//
|
|
// ***********************************************************************
|
|
// Revisions:
|
|
// 1.0 Initial rev
|
|
// 1.1 Added Custom ALU
|
|
// 1.2 Fixed AXI4 slave read first issue
|
|
// 1.3 Added axi full-duplex to half-duplex converter
|
|
// ***********************************************************************
|
|
`timescale 1ns/1ps
|
|
|
|
module apb3_slave #(
|
|
// user parameter starts here
|
|
//
|
|
parameter ADDR_WIDTH = 16,
|
|
parameter DATA_WIDTH = 32,
|
|
parameter NUM_REG = 4
|
|
) (
|
|
// user logic starts here
|
|
input clk,
|
|
input resetn,
|
|
input [ADDR_WIDTH-1:0] PADDR,
|
|
input PSEL,
|
|
input PENABLE,
|
|
output PREADY,
|
|
input PWRITE,
|
|
input [DATA_WIDTH-1:0] PWDATA,
|
|
output [DATA_WIDTH-1:0] PRDATA,
|
|
output PSLVERROR
|
|
|
|
);
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
localparam [1:0] IDLE = 2'b00,
|
|
SETUP = 2'b01,
|
|
ACCESS = 2'b10;
|
|
|
|
integer byteIndex;
|
|
reg [DATA_WIDTH-1:0] slaveReg [0:NUM_REG-1];
|
|
reg [DATA_WIDTH-1:0] slaveRegOut;
|
|
reg [1:0] busState,
|
|
busNext;
|
|
reg slaveReady;
|
|
wire actWrite,
|
|
actRead;
|
|
reg [31:0] lfsr;
|
|
wire lfsr_stop;
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
always@(posedge clk or negedge resetn)
|
|
begin
|
|
if(!resetn)
|
|
busState <= IDLE;
|
|
else
|
|
busState <= busNext;
|
|
end
|
|
|
|
always@(*)
|
|
begin
|
|
busNext = busState;
|
|
|
|
case(busState)
|
|
IDLE:
|
|
begin
|
|
if(PSEL && !PENABLE)
|
|
busNext = SETUP;
|
|
else
|
|
busNext = IDLE;
|
|
end
|
|
SETUP:
|
|
begin
|
|
if(PSEL && PENABLE)
|
|
busNext = ACCESS;
|
|
else
|
|
busNext = IDLE;
|
|
end
|
|
ACCESS:
|
|
begin
|
|
if(PREADY)
|
|
busNext = IDLE;
|
|
else
|
|
busNext = ACCESS;
|
|
end
|
|
default:
|
|
begin
|
|
busNext = IDLE;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
|
|
assign actWrite = PWRITE & (busState == ACCESS);
|
|
assign actRead = !PWRITE & (busState == ACCESS);
|
|
assign PSLVERROR = 1'b0;
|
|
assign PRDATA = slaveRegOut;
|
|
assign PREADY = slaveReady & & (busState !== IDLE);
|
|
|
|
always@ (posedge clk)
|
|
begin
|
|
slaveReady <= actWrite | actRead;
|
|
end
|
|
|
|
always@ (posedge clk or negedge resetn)
|
|
begin
|
|
if(!resetn)
|
|
for(byteIndex = 0; byteIndex < NUM_REG; byteIndex = byteIndex + 1)
|
|
slaveReg[byteIndex] <= {DATA_WIDTH{1'b0}};
|
|
else
|
|
begin
|
|
if(actWrite)
|
|
begin
|
|
for(byteIndex = 0; byteIndex < NUM_REG; byteIndex = byteIndex + 1)
|
|
if (PADDR[3:0] == (byteIndex*4))
|
|
slaveReg[byteIndex] <= PWDATA;
|
|
end
|
|
else
|
|
begin
|
|
slaveReg[0] <= lfsr;
|
|
for(byteIndex = 1; byteIndex < NUM_REG; byteIndex = byteIndex + 1)
|
|
slaveReg[byteIndex] <= slaveReg[byteIndex];
|
|
end
|
|
end
|
|
end
|
|
|
|
always@ (posedge clk or negedge resetn)
|
|
begin
|
|
if(!resetn)
|
|
slaveRegOut <= {DATA_WIDTH{1'b0}};
|
|
else begin
|
|
if(actRead)
|
|
slaveRegOut <= slaveReg[PADDR[7:2]];
|
|
else
|
|
slaveRegOut <= slaveRegOut;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
assign lfsr_stop = slaveReg[1][0];
|
|
//custom logics
|
|
|
|
always@(posedge clk or negedge resetn)
|
|
begin
|
|
if (!resetn)
|
|
lfsr <= 'd1;
|
|
else
|
|
begin
|
|
if(!lfsr_stop)
|
|
begin
|
|
lfsr[31] <= lfsr[0];
|
|
lfsr[30] <= lfsr[31];
|
|
lfsr[29] <= lfsr[30];
|
|
lfsr[28] <= lfsr[29];
|
|
lfsr[27] <= lfsr[28];
|
|
lfsr[26] <= lfsr[27];
|
|
lfsr[25] <= lfsr[26];
|
|
lfsr[24] <= lfsr[25];
|
|
lfsr[23] <= lfsr[24];
|
|
lfsr[22] <= lfsr[23];
|
|
lfsr[21] <= lfsr[22];
|
|
lfsr[20] <= lfsr[21];
|
|
lfsr[19] <= lfsr[20];
|
|
lfsr[18] <= lfsr[19];
|
|
lfsr[17] <= lfsr[18];
|
|
lfsr[16] <= lfsr[17];
|
|
lfsr[15] <= lfsr[16];
|
|
lfsr[14] <= lfsr[15];
|
|
lfsr[13] <= lfsr[14];
|
|
lfsr[12] <= lfsr[13];
|
|
lfsr[11] <= lfsr[12];
|
|
lfsr[10] <= lfsr[11];
|
|
lfsr[9 ] <= lfsr[10];
|
|
lfsr[8 ] <= lfsr[9 ];
|
|
lfsr[7 ] <= lfsr[8 ];
|
|
lfsr[6 ] <= lfsr[7 ];
|
|
lfsr[5 ] <= lfsr[6 ];
|
|
lfsr[4 ] <= lfsr[5 ];
|
|
lfsr[3 ] <= lfsr[4 ] ^ lfsr[0];
|
|
lfsr[2 ] <= lfsr[3 ];
|
|
lfsr[1 ] <= lfsr[2 ];
|
|
lfsr[0 ] <= lfsr[1 ] ^ lfsr[0];
|
|
end
|
|
else
|
|
begin
|
|
lfsr <= lfsr;
|
|
end
|
|
end
|
|
end
|
|
|
|
endmodule
|
|
|
|
// ***********************************************************************
|
|
|
|
module axi4_slave #(
|
|
parameter ADDR_WIDTH = 32,
|
|
parameter DATA_WIDTH = 32
|
|
) (
|
|
//custom logic starts here
|
|
output axi_interrupt,
|
|
//
|
|
input axi_aclk,
|
|
input axi_resetn,
|
|
//AW
|
|
input [7:0] axi_awid,
|
|
input [ADDR_WIDTH-1:0] axi_awaddr,
|
|
input [7:0] axi_awlen,
|
|
input [2:0] axi_awsize,
|
|
input [1:0] axi_awburst,
|
|
input axi_awlock,
|
|
input [3:0] axi_awcache,
|
|
input [2:0] axi_awprot,
|
|
input [3:0] axi_awqos,
|
|
input [3:0] axi_awregion,
|
|
input axi_awvalid,
|
|
output axi_awready,
|
|
//W
|
|
input [DATA_WIDTH-1:0] axi_wdata,
|
|
input [(DATA_WIDTH/8)-1:0]
|
|
axi_wstrb,
|
|
input axi_wlast,
|
|
input axi_wvalid,
|
|
output axi_wready,
|
|
//B
|
|
output [7:0] axi_bid,
|
|
output [1:0] axi_bresp,
|
|
output axi_bvalid,
|
|
input axi_bready,
|
|
//AR
|
|
input [7:0] axi_arid,
|
|
input [ADDR_WIDTH-1:0] axi_araddr,
|
|
input [7:0] axi_arlen,
|
|
input [2:0] axi_arsize,
|
|
input [1:0] axi_arburst,
|
|
input axi_arlock,
|
|
input [3:0] axi_arcache,
|
|
input [2:0] axi_arprot,
|
|
input [3:0] axi_arqos,
|
|
input [3:0] axi_arregion,
|
|
input axi_arvalid,
|
|
output axi_arready,
|
|
//R
|
|
output [7:0] axi_rid,
|
|
output [DATA_WIDTH-1:0] axi_rdata,
|
|
output [1:0] axi_rresp,
|
|
output axi_rlast,
|
|
output axi_rvalid,
|
|
input axi_rready
|
|
);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
localparam RAM_SIZE = 2048;
|
|
localparam RAMW = $clog2(RAM_SIZE);
|
|
|
|
localparam [2:0] IDLE = 3'h0,
|
|
PRE_WR = 3'h1,
|
|
WR = 3'h2,
|
|
WR_RESP = 3'h3,
|
|
PRE_RD = 3'h4,
|
|
RD = 3'h5;
|
|
|
|
reg [2:0] busState,
|
|
busNext;
|
|
wire busReady,
|
|
busPreWrite,
|
|
busWrite,
|
|
busWriteResp,
|
|
busPreRead,
|
|
busRead;
|
|
wire awWrap,
|
|
arWrap;
|
|
reg [7:0] awidReg;
|
|
reg [ADDR_WIDTH-1:0] awaddrReg;
|
|
reg [7:0] awlenReg;
|
|
reg [2:0] awsizeReg;
|
|
reg [1:0] awburstReg,
|
|
awlockReg;
|
|
reg [3:0] awcacheReg;
|
|
reg [2:0] awprotReg;
|
|
reg [3:0] awqosReg;
|
|
reg [3:0] awregionReg;
|
|
|
|
reg [7:0] aridReg;
|
|
reg [ADDR_WIDTH-1:0] araddrReg;
|
|
reg [7:0] arlenReg;
|
|
reg [2:0] arsizeReg;
|
|
reg [1:0] arburstReg,
|
|
arlockReg;
|
|
reg [3:0] arcacheReg;
|
|
reg [2:0] arprotReg;
|
|
reg [3:0] arqosReg;
|
|
reg [3:0] arregionReg;
|
|
|
|
reg [31:0] awaddr_base;
|
|
wire [31:0] awWrapSize;
|
|
reg [7:0] decodeAwsize;
|
|
|
|
wire [31:0] araddr_wrap;
|
|
reg [7:0] decodeArsize;
|
|
|
|
reg [31:0] araddr_base;
|
|
wire [31:0] arWrapSize;
|
|
reg [7:0] ridReg;
|
|
reg [1:0] rrespReg;
|
|
reg [1:0] rlastReg;
|
|
|
|
wire pWr_done;
|
|
wire pRd_done;
|
|
wire awaddr_ext;
|
|
wire araddr_ext;
|
|
wire [(DATA_WIDTH/8)-1:0]
|
|
rlast;
|
|
wire [(DATA_WIDTH/8)-1:0]
|
|
rvalid;
|
|
//custom logic
|
|
wire [9:0] wdata [0:3];
|
|
wire wEnable[0:3];
|
|
wire [9:0] rdata [0:3];
|
|
wire [31:0] data_o;
|
|
wire rEnable;
|
|
reg r_axi_interrupt;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
always@ (posedge axi_aclk or negedge axi_resetn)
|
|
begin
|
|
if(!axi_resetn)
|
|
busState <= IDLE;
|
|
else
|
|
busState <= busNext;
|
|
|
|
end
|
|
|
|
always@ (*)
|
|
begin
|
|
busNext = busState;
|
|
|
|
case(busState)
|
|
IDLE:
|
|
begin
|
|
if(axi_awvalid)
|
|
busNext = PRE_WR;
|
|
else if(axi_arvalid)
|
|
busNext = PRE_RD;
|
|
else
|
|
busNext = IDLE;
|
|
end
|
|
PRE_WR:
|
|
begin
|
|
if(pWr_done)
|
|
busNext = WR;
|
|
else
|
|
busNext = PRE_WR;
|
|
end
|
|
WR:
|
|
begin
|
|
if(axi_wlast)
|
|
busNext = WR_RESP;
|
|
else
|
|
busNext = WR;
|
|
end
|
|
WR_RESP:
|
|
begin
|
|
if(axi_bready)
|
|
busNext = IDLE;
|
|
else
|
|
busNext = WR_RESP;
|
|
end
|
|
PRE_RD:
|
|
begin
|
|
if(pRd_done)
|
|
busNext = RD;
|
|
else
|
|
busNext = PRE_RD;
|
|
end
|
|
RD:
|
|
begin
|
|
if(axi_rlast && axi_rready)
|
|
busNext = IDLE;
|
|
else
|
|
busNext = RD;
|
|
end
|
|
default:
|
|
busNext = IDLE;
|
|
endcase
|
|
end
|
|
|
|
assign busReady = (busState == IDLE);
|
|
assign busPreWrite = (busState == PRE_WR);
|
|
assign busWrite = (busState == WR);
|
|
assign busWriteResp = (busState == WR_RESP);
|
|
assign busPreRead = (busState == PRE_RD);
|
|
assign busRead = (busState == RD);
|
|
|
|
//PRE_WRITE
|
|
assign pWr_done = (awburstReg == 2'b10)? awaddr_ext : 1'b1;
|
|
//AW Control
|
|
|
|
assign axi_awready = busReady;
|
|
|
|
//Wrap Control
|
|
always@ (posedge axi_aclk or negedge axi_resetn)
|
|
begin
|
|
if (!axi_resetn)
|
|
awaddr_base <= 'h0;
|
|
else begin
|
|
if(busReady)
|
|
awaddr_base <= 'h0;
|
|
else if(busPreWrite && !awaddr_ext)
|
|
awaddr_base <= awaddr_base + awWrapSize;
|
|
else
|
|
awaddr_base <= awaddr_base;
|
|
end
|
|
end
|
|
|
|
assign awaddr_ext = busPreWrite ? (awaddr_base[RAMW:0] > awaddrReg[RAMW:0]) : 1'b0;
|
|
assign awWrap = busWrite && (axi_awburst == 2'b10) ? (awaddrReg[RAMW:0] == awaddr_base - 4) : 1'b0;
|
|
assign awWrapSize = (DATA_WIDTH/8) * awlenReg;
|
|
|
|
//AW Info
|
|
always@ (posedge axi_aclk)
|
|
begin
|
|
if(axi_awvalid) begin
|
|
awidReg <= axi_awid;
|
|
awlenReg <= axi_awlen + 1'b1;
|
|
awsizeReg <= axi_awsize;
|
|
awburstReg <= axi_awburst;
|
|
awlockReg <= axi_awlock;
|
|
awcacheReg <= axi_awcache;
|
|
awprotReg <= axi_awprot;
|
|
awqosReg <= axi_awqos;
|
|
awregionReg <= axi_awregion;
|
|
end
|
|
else begin
|
|
awidReg <= awidReg;
|
|
awlenReg <= awlenReg;
|
|
awsizeReg <= awsizeReg;
|
|
awburstReg <= awburstReg;
|
|
awlockReg <= awlockReg;
|
|
awcacheReg <= awcacheReg;
|
|
awprotReg <= awprotReg;
|
|
awqosReg <= awqosReg;
|
|
awregionReg <= awregionReg;
|
|
end
|
|
end
|
|
|
|
always@ (awsizeReg)
|
|
begin
|
|
case(awsizeReg)
|
|
3'h0:decodeAwsize <= 8'd1;
|
|
3'h1:decodeAwsize <= 8'd2;
|
|
3'h2:decodeAwsize <= 8'd4;
|
|
3'h3:decodeAwsize <= 8'd8;
|
|
3'h4:decodeAwsize <= 8'd16;
|
|
3'h5:decodeAwsize <= 8'd32;
|
|
3'h6:decodeAwsize <= 8'd64;
|
|
3'h7:decodeAwsize <= 8'd128;
|
|
default:decodeAwsize <= 8'd1;
|
|
endcase
|
|
end
|
|
|
|
always@ (posedge axi_aclk)
|
|
begin
|
|
if(axi_awvalid)
|
|
awaddrReg <= axi_awaddr;
|
|
else if (busWrite) begin
|
|
case(awburstReg)
|
|
2'b00://fixed burst
|
|
awaddrReg <= awaddrReg;
|
|
2'b01://incremental burst
|
|
awaddrReg <= awaddrReg + decodeAwsize;
|
|
2'b10://wrap burst
|
|
begin
|
|
if(awWrap)
|
|
awaddrReg <= awaddrReg - awWrapSize;
|
|
else
|
|
awaddrReg <= awaddrReg + decodeAwsize;
|
|
end
|
|
default:
|
|
awaddrReg <= awaddrReg;
|
|
endcase
|
|
end
|
|
end
|
|
//W operation
|
|
assign axi_wready = busWrite;
|
|
|
|
//B Response
|
|
assign axi_bid = awidReg;
|
|
assign axi_bresp = 2'b00;
|
|
assign axi_bvalid = busWriteResp;
|
|
|
|
//PRE_READ
|
|
assign pRd_done = (arburstReg == 2'b10)? araddr_ext : 1'b1;
|
|
|
|
//AR Control
|
|
assign axi_arready = busReady;
|
|
|
|
//Wrap Control
|
|
always@ (posedge axi_aclk or negedge axi_resetn)
|
|
begin
|
|
if (!axi_resetn)
|
|
araddr_base <= 'h0;
|
|
else begin
|
|
if(busReady)
|
|
araddr_base <= 'h0;
|
|
else if(busPreRead && !araddr_ext)
|
|
araddr_base <= araddr_base + arWrapSize;
|
|
else
|
|
araddr_base <= araddr_base;
|
|
end
|
|
end
|
|
|
|
assign araddr_ext = busPreRead ? (araddr_base[RAMW:0] > araddrReg[RAMW:0]) : 1'b0;
|
|
assign arWrap = (busRead && axi_arburst == 2'b10) ? (araddrReg[RAMW:0] == araddr_base - 4) : 1'b0;
|
|
assign arWrapSize = (DATA_WIDTH/8) * arlenReg;
|
|
|
|
//AR Info
|
|
always@ (posedge axi_aclk)
|
|
begin
|
|
if(axi_arvalid) begin
|
|
aridReg <= axi_arid;
|
|
arlenReg <= axi_arlen + 1'b1;
|
|
arsizeReg <= axi_arsize;
|
|
arburstReg <= axi_arburst;
|
|
arlockReg <= axi_arlock;
|
|
arcacheReg <= axi_arcache;
|
|
arprotReg <= axi_arprot;
|
|
arqosReg <= axi_arqos;
|
|
arregionReg <= axi_arregion;
|
|
end
|
|
else begin
|
|
aridReg <= aridReg;
|
|
arlenReg <= arlenReg;
|
|
arsizeReg <= arsizeReg;
|
|
arburstReg <= arburstReg;
|
|
arlockReg <= arlockReg;
|
|
arcacheReg <= arcacheReg;
|
|
arprotReg <= arprotReg;
|
|
arqosReg <= arqosReg;
|
|
arregionReg <= arregionReg;
|
|
end
|
|
end
|
|
|
|
always@ (arsizeReg)
|
|
begin
|
|
case(arsizeReg)
|
|
3'h0:decodeArsize <= 8'd1;
|
|
3'h1:decodeArsize <= 8'd2;
|
|
3'h2:decodeArsize <= 8'd4;
|
|
3'h3:decodeArsize <= 8'd8;
|
|
3'h4:decodeArsize <= 8'd16;
|
|
3'h5:decodeArsize <= 8'd32;
|
|
3'h6:decodeArsize <= 8'd64;
|
|
3'h7:decodeArsize <= 8'd128;
|
|
default:decodeArsize <= 8'd1;
|
|
endcase
|
|
end
|
|
|
|
always@ (posedge axi_aclk)
|
|
begin
|
|
if(axi_arvalid)
|
|
araddrReg <= axi_araddr;
|
|
else if (rEnable && axi_rready) begin
|
|
case(arburstReg)
|
|
2'b00://fixed burst
|
|
araddrReg <= araddrReg;
|
|
2'b01://incremental burst
|
|
araddrReg <= araddrReg + decodeArsize;
|
|
2'b10://wrap burst
|
|
begin
|
|
if(arWrap)
|
|
araddrReg <= araddrReg - arWrapSize;
|
|
else
|
|
araddrReg <= araddrReg + decodeArsize;
|
|
end
|
|
default:
|
|
araddrReg <= araddrReg;
|
|
endcase
|
|
end
|
|
end
|
|
|
|
// R Operation
|
|
assign axi_rdata = data_o;
|
|
|
|
// R Response
|
|
assign axi_rvalid = busRead? |rvalid : 1'b0 ;
|
|
assign axi_rlast = busRead? |rlast : 1'b0 ;
|
|
|
|
assign axi_rresp = 2'b00;
|
|
assign axi_rid = aridReg;
|
|
|
|
//custom logic starts here
|
|
assign axi_interrupt = r_axi_interrupt;
|
|
assign rEnable = (axi_arburst == 2'b10)? busRead : busPreRead;
|
|
|
|
always@ (posedge axi_aclk)
|
|
begin
|
|
if (!axi_resetn)
|
|
begin
|
|
r_axi_interrupt <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
if((axi_wvalid) && (axi_wdata == 16'hABCD))
|
|
r_axi_interrupt <= 1'b1;
|
|
else
|
|
r_axi_interrupt <= 1'b0;
|
|
end
|
|
end
|
|
|
|
genvar i;
|
|
generate
|
|
for(i=0;i < (DATA_WIDTH/8); i = i + 1) begin
|
|
|
|
assign rvalid[i] = (arlenReg != 'h1)? rdata[i][8] : 1'b1;
|
|
assign rlast[i] = (arlenReg != 'h1)? rdata[i][9] : 1'b1;
|
|
assign wdata[i] = {axi_wlast, axi_wvalid, axi_wdata[(i*8+7) -: 8]} ;
|
|
assign data_o[(i*8+7) -: 8] = rdata[i];
|
|
assign wEnable[i] = axi_wready & axi_wvalid & axi_wstrb[i];
|
|
|
|
ext_mem #(
|
|
.DATA_WIDTH (10),
|
|
.ADDR_WIDTH (RAMW-2),
|
|
.OUTPUT_REG ("TRUE")
|
|
|
|
) user_ram (
|
|
.wdata (wdata[i]),
|
|
.waddr (awaddrReg[RAMW-1:2]),
|
|
.raddr (araddrReg[RAMW-1:2]),
|
|
.we (wEnable[i]),
|
|
.wclk (axi_aclk),
|
|
.re (rEnable),
|
|
.rclk (axi_aclk),
|
|
.rdata (rdata[i])
|
|
);
|
|
end
|
|
endgenerate
|
|
|
|
endmodule
|
|
|
|
// ***********************************************************************
|
|
|
|
module memory_checker #(
|
|
parameter WIDTH = 32,
|
|
parameter ALEN = 23,
|
|
parameter START_ADDR = 32'h00000000,
|
|
parameter STOP_ADDR = 32'h00100000,
|
|
parameter ADDR_OFFSET = (ALEN + 1)*(WIDTH/8)
|
|
) (
|
|
input axi_clk,
|
|
input rstn,
|
|
input start,
|
|
output [7:0] aid,
|
|
output reg [31:0] aaddr,
|
|
output reg [7:0] alen,
|
|
output reg [2:0] asize,
|
|
output reg [1:0] aburst,
|
|
output reg [1:0] alock,
|
|
output reg avalid,
|
|
input aready,
|
|
output reg atype,
|
|
|
|
output [7:0] wid,
|
|
output reg [WIDTH-1:0] wdata,
|
|
output [WIDTH/8-1:0] wstrb,
|
|
output reg wlast,
|
|
output reg wvalid,
|
|
input wready,
|
|
|
|
input [3:0] rid,
|
|
input [WIDTH-1:0] rdata,
|
|
input rlast,
|
|
input rvalid,
|
|
output reg rready,
|
|
input [1:0] rresp,
|
|
|
|
input [7:0] bid,
|
|
input bvalid,
|
|
output reg bready,
|
|
output pass
|
|
|
|
);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
localparam ASIZE = (WIDTH == 512)? 6 :
|
|
(WIDTH == 256)? 5 :
|
|
(WIDTH == 128)? 4 :
|
|
(WIDTH == 64)? 3 : 2;
|
|
|
|
//Main states
|
|
localparam COMPARE_WIDTH = WIDTH;
|
|
localparam IDLE = 4'b0000,
|
|
WRITE_ADDR = 4'b0001,
|
|
PRE_WRITE = 4'b0010,
|
|
WRITE = 4'b0011,
|
|
POST_WRITE = 4'b0100,
|
|
READ_ADDR = 4'b0101,
|
|
PRE_READ = 4'b0110,
|
|
READ_COMPARE = 4'b0111,
|
|
POST_READ = 4'b1000,
|
|
DONE = 4'b1001;
|
|
|
|
//reg [3:0] states, nstates;
|
|
reg fail;
|
|
reg done;
|
|
reg [3:0] states;
|
|
reg [3:0] nstates;
|
|
reg bvalid_done;
|
|
reg [1:0] start_sync;
|
|
reg [8:0] write_cnt, read_cnt;
|
|
reg [WIDTH-1:0] rdata_store;
|
|
reg wburst_done,
|
|
rburst_done,
|
|
write_done,
|
|
read_done;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
assign aid = 8'h00;
|
|
assign wstrb = {WIDTH/8{1'b1}};
|
|
assign wid = 8'h00;
|
|
assign pass = done & ~fail;
|
|
|
|
always @(posedge axi_clk or negedge rstn)
|
|
begin
|
|
if (!rstn) begin
|
|
start_sync <= 2'b00;
|
|
end else begin
|
|
start_sync[0] <= start;
|
|
start_sync[1] <= start_sync[0];
|
|
end
|
|
end
|
|
|
|
always @(posedge axi_clk or negedge rstn)
|
|
begin
|
|
if (!rstn) begin
|
|
states <= IDLE;
|
|
end else begin
|
|
states <= nstates;
|
|
end
|
|
end
|
|
|
|
always @(states or start_sync[1] or write_cnt or rburst_done or write_done or read_done or bvalid_done or aready)
|
|
begin
|
|
case(states)
|
|
IDLE :
|
|
if (start_sync[1])
|
|
nstates = WRITE_ADDR;
|
|
else
|
|
nstates = IDLE;
|
|
WRITE_ADDR :
|
|
if (aready)
|
|
nstates = PRE_WRITE;
|
|
else
|
|
nstates = WRITE_ADDR;
|
|
PRE_WRITE :
|
|
nstates = WRITE;
|
|
WRITE :
|
|
if (write_cnt == 9'd0)
|
|
nstates = POST_WRITE;
|
|
else
|
|
nstates = WRITE;
|
|
POST_WRITE :
|
|
if (write_done & bvalid_done)
|
|
nstates = READ_ADDR;
|
|
else if (bvalid_done)
|
|
nstates = WRITE_ADDR;
|
|
else
|
|
nstates = POST_WRITE;
|
|
READ_ADDR :
|
|
if (aready)
|
|
nstates = PRE_READ;
|
|
else
|
|
nstates = READ_ADDR;
|
|
PRE_READ :
|
|
nstates = READ_COMPARE;
|
|
READ_COMPARE :
|
|
if (rburst_done)
|
|
nstates = POST_READ;
|
|
else
|
|
nstates = READ_COMPARE;
|
|
POST_READ :
|
|
if (read_done)
|
|
nstates = DONE;
|
|
else
|
|
nstates = READ_ADDR;
|
|
DONE :
|
|
nstates = DONE;
|
|
default :
|
|
nstates = IDLE;
|
|
endcase
|
|
end
|
|
|
|
always @(posedge axi_clk or negedge rstn)
|
|
begin
|
|
if (!rstn) begin
|
|
aaddr <= START_ADDR;
|
|
avalid <= 1'b0;
|
|
atype <= 1'b0;
|
|
aburst <= 2'b00;
|
|
asize <= 3'b000;
|
|
alen <= 8'd0;
|
|
alock <= 2'b00;
|
|
wvalid <= 1'b0;
|
|
write_cnt <= ALEN + 1;
|
|
write_done <= 1'b0;
|
|
wdata <= {WIDTH{1'b0}};
|
|
wburst_done <= 1'b0;
|
|
wlast <= 1'b0;
|
|
bready <= 1'b0;
|
|
fail <= 1'b0;
|
|
done <= 1'b0;
|
|
rready <= 1'b0;
|
|
bvalid_done <=1'b0;
|
|
end
|
|
else
|
|
begin
|
|
if (states == IDLE)
|
|
begin
|
|
aaddr <= START_ADDR;
|
|
avalid <= 1'b0;
|
|
atype <= 1'b0;
|
|
aburst <= 2'b00;
|
|
asize <= 3'b000;
|
|
alen <= 8'd0;
|
|
alock <= 2'b00;
|
|
wvalid <= 1'b0;
|
|
write_cnt <= ALEN + 1;
|
|
wdata <= {WIDTH{1'b0}};
|
|
wburst_done <= 1'b0;
|
|
wlast <= 1'b0;
|
|
bready <= 1'b0;
|
|
rready <= 1'b0;
|
|
bvalid_done <= 1'b0;
|
|
fail <= 1'b0;
|
|
done <= 1'b0;
|
|
end
|
|
if (states == WRITE_ADDR)
|
|
begin
|
|
avalid <= 1'b1;
|
|
atype <= 1'b1;
|
|
asize <= ASIZE;
|
|
alen <= ALEN;
|
|
aburst <= 2'b01;
|
|
alock <= 2'b00;
|
|
wvalid <= 1'b0;
|
|
write_cnt <= ALEN + 1;
|
|
wburst_done <= 1'b0;
|
|
bvalid_done <= 1'b0;
|
|
bready <= 1'b0;
|
|
rready <= 1'b0;
|
|
done <= 1'b0;
|
|
fail <= 1'b0;
|
|
end
|
|
if (states == PRE_WRITE)
|
|
begin
|
|
avalid <= 1'b0;
|
|
atype <= 1'b0;
|
|
wvalid <= 1'b1;
|
|
wdata <= {{WIDTH/32{~aaddr[7:0]}},{WIDTH/32{~write_cnt[7:0]}},{WIDTH/32{aaddr[7:0]}},{WIDTH/32{write_cnt[7:0]}}};
|
|
bready <= 1'b1;
|
|
write_cnt <= write_cnt - 1;
|
|
if(alen == 'd0)
|
|
begin
|
|
wlast <= 1'b1;
|
|
end
|
|
end
|
|
if (states == WRITE)
|
|
begin
|
|
if (wready == 1'b1)
|
|
begin
|
|
wdata <= {{WIDTH/32{~aaddr[7:0]}},{WIDTH/32{~write_cnt[7:0]}},{WIDTH/32{aaddr[7:0]}},{WIDTH/32{write_cnt[7:0]}}};
|
|
if (write_cnt == 9'd0)
|
|
begin
|
|
wburst_done <= 1'b1;
|
|
wlast <= 1'b0;
|
|
wvalid <= 1'b0;
|
|
if (aaddr >= STOP_ADDR)
|
|
begin
|
|
write_done <= 1'b1;
|
|
end else
|
|
begin
|
|
write_done <= 1'b0;
|
|
end
|
|
end if (write_cnt == 9'd1)
|
|
begin
|
|
wlast <= 1'b1;
|
|
write_cnt <= write_cnt - 1;
|
|
end
|
|
else
|
|
begin
|
|
write_cnt <= write_cnt - 1;
|
|
end
|
|
end
|
|
end
|
|
if (states == POST_WRITE)
|
|
begin
|
|
if (write_done)
|
|
begin
|
|
aaddr <= START_ADDR;
|
|
end
|
|
else
|
|
begin
|
|
if (bvalid) begin
|
|
aaddr <= aaddr + ADDR_OFFSET;
|
|
end
|
|
end
|
|
if (wready == 1'b1)
|
|
begin
|
|
wlast <= 1'b0;
|
|
wvalid <= 1'b0;
|
|
end
|
|
if (bvalid)
|
|
begin
|
|
bvalid_done <= 1'b1;
|
|
bready <= 1'b0;
|
|
end
|
|
end
|
|
if (states == READ_ADDR)
|
|
begin
|
|
avalid <= 1'b1;
|
|
read_cnt <= ALEN + 1;
|
|
|
|
end
|
|
if (states == PRE_READ)
|
|
begin
|
|
avalid <= 1'b0;
|
|
rburst_done <= 1'b0;
|
|
rdata_store <= {{WIDTH/32{~aaddr[7:0]}},{WIDTH/32{~read_cnt[7:0]}},{WIDTH/32{aaddr[7:0]}},{WIDTH/32{read_cnt[7:0]}}};
|
|
read_cnt <= read_cnt - 1'b1;
|
|
end
|
|
if (states == READ_COMPARE)
|
|
begin
|
|
rready <= 1'b1;
|
|
if (read_cnt != 9'd0)
|
|
begin
|
|
if (rvalid == 1'b1)
|
|
begin
|
|
rdata_store <= {{WIDTH/32{~aaddr[7:0]}},{WIDTH/32{~read_cnt[7:0]}},{WIDTH/32{aaddr[7:0]}},{WIDTH/32{read_cnt[7:0]}}};
|
|
read_cnt <= read_cnt - 1'b1;
|
|
if (rdata[COMPARE_WIDTH-1:0] != rdata_store[COMPARE_WIDTH-1:0])
|
|
fail <= 1'b1;
|
|
else
|
|
fail <= 1'b0;
|
|
end
|
|
|
|
end
|
|
end
|
|
if (read_cnt == 9'd0)
|
|
begin
|
|
if (rvalid == 1'b1)
|
|
begin
|
|
if (rdata[COMPARE_WIDTH-1:0] != rdata_store[COMPARE_WIDTH-1:0])
|
|
begin
|
|
fail <= 1'b1;
|
|
end
|
|
else
|
|
begin
|
|
fail <= 1'b0;
|
|
end
|
|
if (aaddr >= STOP_ADDR)
|
|
begin
|
|
read_done <= 1'b1;
|
|
end
|
|
else
|
|
begin
|
|
read_done <= 1'b0;
|
|
end
|
|
rburst_done <= 1'b1;
|
|
end
|
|
end
|
|
if (states == POST_READ)
|
|
begin
|
|
aaddr <= aaddr + ADDR_OFFSET;
|
|
rready <= 1'b1;
|
|
end
|
|
if (states == DONE)
|
|
begin
|
|
done <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
endmodule
|
|
|
|
// ***********************************************************************
|
|
module timer_start #(
|
|
parameter MHZ = 50,
|
|
parameter SECOND = 3,
|
|
parameter PULSE = 0
|
|
) (
|
|
input clk,
|
|
input rst_n,
|
|
output start
|
|
);
|
|
|
|
reg [35:0] delay_cnt;
|
|
wire second_tick;
|
|
reg [4:0] second_cnt;
|
|
reg [3:0] pulse_reg;
|
|
wire start_reg;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
`ifndef EFX_SIM
|
|
localparam tick_cnt = (MHZ * 1000000) >> 1;
|
|
`else
|
|
localparam tick_cnt = MHZ * 200;
|
|
`endif
|
|
|
|
always@(posedge clk or negedge rst_n)
|
|
begin
|
|
if(!rst_n)
|
|
delay_cnt <= 'd0;
|
|
else
|
|
begin
|
|
if(delay_cnt == tick_cnt || start_reg == 1'b1)
|
|
delay_cnt <= 'd0;
|
|
else
|
|
delay_cnt <= delay_cnt + 1'b1;
|
|
end
|
|
end
|
|
|
|
assign second_tick = ((delay_cnt) == (tick_cnt - 1));
|
|
|
|
always@(posedge clk or negedge rst_n)
|
|
begin
|
|
if(!rst_n)
|
|
second_cnt <= 'd0;
|
|
else
|
|
begin
|
|
if(second_tick)
|
|
second_cnt <= second_cnt + 1'b1;
|
|
else
|
|
second_cnt <= second_cnt;
|
|
end
|
|
end
|
|
|
|
assign start_reg = (second_cnt == SECOND);
|
|
|
|
always@(posedge clk)
|
|
begin
|
|
pulse_reg <= {pulse_reg[2:0],start_reg};
|
|
end
|
|
|
|
generate
|
|
if(PULSE == 1)
|
|
assign start = ~pulse_reg[3] & start_reg;
|
|
else
|
|
assign start = start_reg;
|
|
endgenerate
|
|
|
|
endmodule
|
|
|
|
// ***********************************************************************
|
|
module ext_mem #(
|
|
parameter DATA_WIDTH = 8,
|
|
parameter ADDR_WIDTH = 9,
|
|
parameter OUTPUT_REG = "TRUE",
|
|
parameter RAM_INIT_FILE = ""
|
|
) (
|
|
input [DATA_WIDTH-1:0] wdata,
|
|
input [ADDR_WIDTH-1:0] waddr,
|
|
input [ADDR_WIDTH-1:0] raddr,
|
|
input we,
|
|
input wclk,
|
|
input re,
|
|
input rclk,
|
|
output [DATA_WIDTH-1:0] rdata
|
|
);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
localparam MEMORY_DEPTH = 2**ADDR_WIDTH;
|
|
localparam MAX_DATA = (1<<ADDR_WIDTH)-1;
|
|
|
|
reg [DATA_WIDTH-1:0]ram [MEMORY_DEPTH-1:0];
|
|
wire [DATA_WIDTH-1:0] r_rdata_1P;
|
|
reg [DATA_WIDTH-1:0] r_rdata_2P = 'h0;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
initial
|
|
begin
|
|
if (RAM_INIT_FILE != "")
|
|
begin
|
|
$readmemh(RAM_INIT_FILE, ram);
|
|
end
|
|
end
|
|
|
|
always @ (posedge wclk)
|
|
if (we)
|
|
ram[waddr] <= wdata;
|
|
|
|
assign r_rdata_1P = re? ram[raddr] : 'hZ;
|
|
|
|
always @ (posedge rclk)
|
|
begin
|
|
if (re)
|
|
r_rdata_2P <= r_rdata_1P;
|
|
end
|
|
|
|
generate
|
|
if (OUTPUT_REG == "TRUE")
|
|
assign rdata = r_rdata_2P;
|
|
else
|
|
assign rdata = r_rdata_1P;
|
|
endgenerate
|
|
|
|
endmodule
|
|
|
|
// ***********************************************************************
|
|
module custom_instruction_tea (
|
|
input clk,
|
|
input reset,
|
|
input cmd_valid,
|
|
output cmd_ready,
|
|
input [9:0] cmd_function_id,
|
|
input [31:0] cmd_inputs_0,
|
|
input [31:0] cmd_inputs_1,
|
|
output reg rsp_valid,
|
|
input rsp_ready,
|
|
output [31:0] rsp_outputs_0
|
|
);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
reg [31:0] raw_data0;
|
|
reg [31:0] raw_data1;
|
|
reg raw_valid;
|
|
reg raw_valid_upper;
|
|
reg [1:0] valid_upper_r1;
|
|
wire [63:0] enc_out;
|
|
wire enc_valid;
|
|
wire enc_valid_upper;
|
|
reg enc_busy;
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
always@(posedge clk or posedge reset)
|
|
begin
|
|
if(reset)
|
|
begin
|
|
raw_data0 <= 32'd0;
|
|
raw_data1 <= 32'd0;
|
|
raw_valid <= 1'b0;
|
|
raw_valid_upper <= raw_valid_upper;
|
|
end
|
|
else
|
|
begin
|
|
if (cmd_ready & cmd_valid)
|
|
begin
|
|
case (cmd_function_id[1:0])
|
|
2'd0:
|
|
begin
|
|
raw_data0 <= cmd_inputs_0;
|
|
raw_data1 <= cmd_inputs_1;
|
|
raw_valid <= 1'b1;
|
|
raw_valid_upper <= 1'b0;
|
|
|
|
end
|
|
2'd1:
|
|
begin
|
|
raw_data0 <= raw_data0;
|
|
raw_data1 <= raw_data1;
|
|
raw_valid <= 1'b0;
|
|
raw_valid_upper <= 1'b1;
|
|
end
|
|
default:
|
|
begin
|
|
raw_data0 <= raw_data0;
|
|
raw_data1 <= raw_data1;
|
|
raw_valid <= 1'b0;
|
|
raw_valid_upper <= raw_valid_upper;
|
|
end
|
|
endcase
|
|
end
|
|
else
|
|
begin
|
|
raw_data0 <= raw_data0;
|
|
raw_data1 <= raw_data1;
|
|
raw_valid <= 1'b0;
|
|
raw_valid_upper <= raw_valid_upper;
|
|
end
|
|
end
|
|
end
|
|
|
|
always@(posedge clk or posedge reset)
|
|
begin
|
|
if(reset)
|
|
enc_busy <= 1'b0;
|
|
else
|
|
begin
|
|
if(rsp_valid && rsp_ready)
|
|
enc_busy <= 1'b0;
|
|
else if(cmd_valid)
|
|
begin
|
|
case (cmd_function_id[1:0])
|
|
2'd0,2'd1:
|
|
enc_busy <= 1'b1;
|
|
default:
|
|
enc_busy <= 1'b0;
|
|
endcase
|
|
end
|
|
else
|
|
enc_busy <= enc_busy;
|
|
end
|
|
end
|
|
|
|
always@(posedge clk)
|
|
begin
|
|
valid_upper_r1 <= {valid_upper_r1[0], raw_valid_upper};
|
|
end
|
|
|
|
assign enc_valid_upper = valid_upper_r1[0] & ~valid_upper_r1[1];
|
|
|
|
always@(posedge clk or posedge reset)
|
|
begin
|
|
if(reset)
|
|
rsp_valid <= 1'b0;
|
|
else
|
|
begin
|
|
if(enc_valid | enc_valid_upper)
|
|
rsp_valid <= 1'b1;
|
|
else if(rsp_ready)
|
|
rsp_valid <= 1'b0;
|
|
else
|
|
rsp_valid <= rsp_valid;
|
|
end
|
|
end
|
|
|
|
|
|
assign rsp_outputs_0 = raw_valid_upper ? enc_out[63:32]:enc_out[31:0];
|
|
assign cmd_ready = !enc_busy;
|
|
|
|
tiny_encrytion #(
|
|
.ITER(1024)
|
|
) tea (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
.raw0 (raw_data0),
|
|
.raw1 (raw_data1),
|
|
.rawEn (raw_valid),
|
|
.busy (),
|
|
.enc_out (enc_out),
|
|
.enc_valid (enc_valid)
|
|
);
|
|
|
|
endmodule
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
module tiny_encrytion #(
|
|
parameter ITER = 1024
|
|
) (
|
|
clk,
|
|
reset,
|
|
raw0,
|
|
raw1,
|
|
rawEn,
|
|
busy,
|
|
enc_out,
|
|
enc_valid
|
|
|
|
);
|
|
|
|
input clk;
|
|
input reset;
|
|
input [31:0] raw0;
|
|
input [31:0] raw1;
|
|
input rawEn;
|
|
output busy;
|
|
output reg [63:0] enc_out;
|
|
output enc_valid;
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
localparam deltaConstant = 32'h9E3779B9;
|
|
localparam enckey0 = 32'h01234567;
|
|
localparam enckey1 = 32'h89abcdef;
|
|
localparam enckey2 = 32'h13579248;
|
|
localparam enckey3 = 32'h248a0135;
|
|
localparam CW = $clog2(ITER);
|
|
|
|
reg [31:0] raw_r0,
|
|
raw_r1;
|
|
|
|
reg [CW-1:0] iteration_cnt;
|
|
reg [2:0] iteration_start;
|
|
wire iteration_stop;
|
|
reg iteration_act;
|
|
reg [1:0] data_tick;
|
|
reg data_tick_r1;
|
|
reg [31:0] delta_r1;
|
|
|
|
wire [31:0] cal0_top;
|
|
wire [31:0] cal0_mid;
|
|
wire [31:0] cal0_bot;
|
|
wire [31:0] cal0;
|
|
|
|
wire [31:0] cal1_top;
|
|
wire [31:0] cal1_mid;
|
|
wire [31:0] cal1_bot;
|
|
wire [31:0] cal1;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
always@(posedge clk)
|
|
begin
|
|
if(data_tick[0])
|
|
enc_out <= {raw_r1, raw_r0};
|
|
else
|
|
enc_out <= enc_out;
|
|
end
|
|
|
|
assign busy = iteration_act;
|
|
assign enc_valid = data_tick[1];
|
|
|
|
always@(posedge clk)
|
|
begin
|
|
iteration_start <= {iteration_start[1:0], rawEn};
|
|
data_tick <= {data_tick[0], iteration_stop};
|
|
end
|
|
|
|
assign iteration_stop = (iteration_cnt == {CW{1'b1}});
|
|
|
|
always@(posedge clk or posedge reset)
|
|
begin
|
|
if(reset)
|
|
iteration_act <= 'b0;
|
|
else
|
|
begin
|
|
if(iteration_start[2])
|
|
iteration_act <= 1'b1;
|
|
else if(iteration_stop)
|
|
iteration_act <= 1'b0;
|
|
else
|
|
iteration_act <= iteration_act;
|
|
end
|
|
end
|
|
|
|
always@(posedge clk or posedge reset)
|
|
begin
|
|
if(reset)
|
|
iteration_cnt <= 'd0;
|
|
else
|
|
begin
|
|
if(iteration_act)
|
|
iteration_cnt <= iteration_cnt + 1'b1;
|
|
else
|
|
iteration_cnt <= 'd0;
|
|
end
|
|
end
|
|
|
|
always@(posedge clk)
|
|
begin
|
|
if(iteration_start[1] && !iteration_act)
|
|
begin
|
|
raw_r0 <= raw0;
|
|
raw_r1 <= raw1;
|
|
delta_r1 <= deltaConstant;
|
|
end
|
|
else
|
|
if(iteration_act)
|
|
begin
|
|
raw_r0 <= cal1 + raw_r0;
|
|
raw_r1 <= cal0 + raw_r1;
|
|
delta_r1 <= delta_r1 + deltaConstant;
|
|
end
|
|
else
|
|
begin
|
|
raw_r0 <= raw_r0;
|
|
raw_r1 <= raw_r1;
|
|
delta_r1 <= delta_r1;
|
|
|
|
end
|
|
end
|
|
|
|
|
|
assign cal0_top = ((raw_r0 + cal1) << 4) + enckey2;
|
|
assign cal0_mid = (raw_r0 + cal1) + delta_r1;
|
|
assign cal0_bot = ((raw_r0 + cal1) >> 5) + enckey3;
|
|
assign cal0 = cal0_top ^ cal0_mid ^ cal0_bot;
|
|
assign cal1_top = (raw_r1 << 4) + enckey0;
|
|
assign cal1_mid = raw_r1 + delta_r1;
|
|
assign cal1_bot = (raw_r1 >> 5) + enckey1;
|
|
assign cal1 = cal1_top ^ cal1_mid ^ cal1_bot;
|
|
|
|
endmodule
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
module fd_to_hd_wrapper (
|
|
input clk,
|
|
input reset,
|
|
output wire io_ddrA_arw_valid,
|
|
input io_ddrA_arw_ready,
|
|
output wire [31:0] io_ddrA_arw_payload_addr,
|
|
output wire [7:0] io_ddrA_arw_payload_id,
|
|
output wire [7:0] io_ddrA_arw_payload_len,
|
|
output wire [2:0] io_ddrA_arw_payload_size,
|
|
output wire [1:0] io_ddrA_arw_payload_burst,
|
|
output wire [1:0] io_ddrA_arw_payload_lock,
|
|
output wire io_ddrA_arw_payload_write,
|
|
|
|
input io_ddrA_aw_valid,
|
|
output wire io_ddrA_aw_ready,
|
|
input [31:0] io_ddrA_aw_payload_addr,
|
|
input [7:0] io_ddrA_aw_payload_id,
|
|
input [7:0] io_ddrA_aw_payload_len,
|
|
input [2:0] io_ddrA_aw_payload_size,
|
|
input [1:0] io_ddrA_aw_payload_burst,
|
|
input [1:0] io_ddrA_aw_payload_lock,
|
|
|
|
input io_ddrA_ar_valid,
|
|
output wire io_ddrA_ar_ready,
|
|
input [31:0] io_ddrA_ar_payload_addr,
|
|
input [7:0] io_ddrA_ar_payload_id,
|
|
input [7:0] io_ddrA_ar_payload_len,
|
|
input [2:0] io_ddrA_ar_payload_size,
|
|
input [1:0] io_ddrA_ar_payload_burst,
|
|
input [1:0] io_ddrA_ar_payload_lock
|
|
);
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
localparam [1:0] IDLE = 2'h0,
|
|
WRITE = 2'h1,
|
|
READ = 2'h2;
|
|
|
|
reg [1:0] st_cur,
|
|
st_next;
|
|
|
|
wire op_write,
|
|
op_read;
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
always@(posedge clk or posedge reset)
|
|
begin
|
|
if(reset)
|
|
st_cur <= IDLE;
|
|
else
|
|
st_cur <= st_next;
|
|
end
|
|
|
|
always@*
|
|
begin
|
|
st_next = st_cur;
|
|
case(st_cur)
|
|
IDLE:
|
|
begin
|
|
if(io_ddrA_aw_valid)
|
|
st_next = WRITE;
|
|
else if (io_ddrA_ar_valid)
|
|
st_next = READ;
|
|
else
|
|
st_next = IDLE;
|
|
end
|
|
WRITE:
|
|
begin
|
|
if(io_ddrA_aw_ready)
|
|
st_next = IDLE;
|
|
else
|
|
st_next = WRITE;
|
|
end
|
|
READ:
|
|
begin
|
|
if(io_ddrA_ar_ready)
|
|
st_next = IDLE;
|
|
else
|
|
st_next = READ;
|
|
end
|
|
default: st_next = IDLE;
|
|
endcase
|
|
end
|
|
|
|
assign op_write = (st_cur == WRITE);
|
|
assign op_read = (st_cur == READ);
|
|
|
|
assign io_ddrA_arw_valid = op_write ? io_ddrA_aw_valid : op_read ? io_ddrA_ar_valid : 1'b0;
|
|
assign io_ddrA_arw_payload_addr = op_write ? io_ddrA_aw_payload_addr : io_ddrA_ar_payload_addr;
|
|
assign io_ddrA_arw_payload_id = op_write ? io_ddrA_aw_payload_id : io_ddrA_ar_payload_id;
|
|
assign io_ddrA_arw_payload_len = op_write ? io_ddrA_aw_payload_len : io_ddrA_ar_payload_len;
|
|
assign io_ddrA_arw_payload_size = op_write ? io_ddrA_aw_payload_size : io_ddrA_ar_payload_size;
|
|
assign io_ddrA_arw_payload_burst = op_write ? io_ddrA_aw_payload_burst : io_ddrA_ar_payload_burst;
|
|
assign io_ddrA_arw_payload_lock = op_write ? io_ddrA_aw_payload_lock : io_ddrA_ar_payload_lock;
|
|
assign io_ddrA_arw_payload_write = op_write;
|
|
|
|
assign io_ddrA_aw_ready = op_write ? io_ddrA_arw_ready : 1'b0;
|
|
assign io_ddrA_ar_ready = op_read ? io_ddrA_arw_ready : 1'b0;
|
|
|
|
endmodule
|