// This module has a set of serial registers that can be used to
// interface to an 8 bit wide 2MB chip.
// drive/strobe rd works by driving data when RD is high or pos edge
// of CLK reads in while nRD is low
//
// Toggle nCtrl high low high to strobe chip control register to pins
// Usage requires a software driver that does the following:
//
// Reset:
// bring pin_ENABLE high,
// bring pin_nCTRL high
// toggle pin_CLK low high low
// bring pin_nCTRL low
// toggle pin_CLK low high low
// toggle pin_CLK low high low
// toggle pin_CLK low high low
// bring pin_nCTRL high
// bring pin_ENABLE low
//
// Write A[3:0] bits of address bus;
// bring pin_nCTRL low
// put 0 on pin_Din
// toggle pin_CLK high low
// put 0 on pin_Din
// toggle pin_CLK high low
// put 1 on pin_Din
// toggle pin_CLK high low
// bring pin_nCTRL high
// put A[0] in pin_Din
// toggle pin_CLK high low
// put A[1] in pin_Din
// toggle pin_CLK high low
// put A[2] in pin_Din
// toggle pin_CLK high low
// put A[3] in pin_Din
// toggle pin_CLK high low
//
// Write A[7:4] bits of address bus;
// bring pin_nCTRL low
// put 0 on pin_Din
// toggle pin_CLK high low
// put 1 on pin_Din
// toggle pin_CLK high low
// put 0 on pin_Din
// toggle pin_CLK high low
// bring pin_nCTRL high
// put A[4] in pin_Din
// toggle pin_CLK high low
// put A[5] in pin_Din
// toggle pin_CLK high low
// put A[6] in pin_Din
// toggle pin_CLK high low
// put A[7] in pin_Din
// toggle pin_CLK high low
//
// Write A[17:8] bits of address bus;
// bring pin_nCTRL low
// put 1 on pin_Din
// toggle pin_CLK high low
// put 1 on pin_Din
// toggle pin_CLK high low
// put 0 on pin_Din
// toggle pin_CLK high low
// bring pin_nCTRL high
// put A[8] in pin_Din
// toggle pin_CLK high low
// put A[9] in pin_Din
// toggle pin_CLK high low
// put A[10] in pin_Din
// toggle pin_CLK high low
// put A[11] in pin_Din
// toggle pin_CLK high low
// put A[12] in pin_Din
// toggle pin_CLK high low
// put A[13] in pin_Din
// toggle pin_CLK high low
// put A[14] in pin_Din
// toggle pin_CLK high low
// put A[15] in pin_Din
// toggle pin_CLK high low
// put A[16] in pin_Din
// toggle pin_CLK high low
// put A[17] in pin_Din
// toggle pin_CLK high low
//
// Write drive/rdstrobe RD* WR* CS*
// bring pin_nCTRL low
// put 1 on pin_Din
// toggle pin_CLK high low
// put 1 on pin_Din
// toggle pin_CLK high low
// put 1 on pin_Din
// toggle pin_CLK high low
// bring pin_nCTRL high
// put RD* in pin_Din
// toggle pin_CLK high low
// put WR* in pin_Din
// toggle pin_CLK high low
// put CS* in pin_Din
// toggle pin_CLK high low
// put drive/rdstrobe in pin_Din
// toggle pin_CLK high low
//
// Write data bus to be asserted while WR* low;
// bring pin_nCTRL low
// put 0 on pin_Din
// toggle pin_CLK high low
// put 0 on pin_Din
// toggle pin_CLK high low
// put 0 on pin_Din
// toggle pin_CLK high low
// bring pin_nCTRL high
// put D[0] in pin_Din
// toggle pin_CLK high low
// put D[1] in pin_Din
// toggle pin_CLK high low
// put D[2] in pin_Din
// toggle pin_CLK high low
// put D[3] in pin_Din
// toggle pin_CLK high low
// put D[4] in pin_Din
// toggle pin_CLK high low
// put D[5] in pin_Din
// toggle pin_CLK high low
// put D[6] in pin_Din
// toggle pin_CLK high low
// put D[7] in pin_Din
// toggle pin_CLK high low
//
// Load data bus read on RD* rising edge;
// bring pin_nCTRL low
// put 0 on pin_Din
// toggle pin_CLK high low
// put 0 on pin_Din
// toggle pin_CLK high low
// put 0 on pin_Din
// toggle pin_CLK high low
// bring pin_nCTRL high
// toggle pin_CLK high low
// data = (data >> 1) | (pin_Dout << 7)
// toggle pin_CLK high low
// data = (data >> 1) | (pin_Dout << 7)
// toggle pin_CLK high low
// data = (data >> 1) | (pin_Dout << 7)
// toggle pin_CLK high low
// data = (data >> 1) | (pin_Dout << 7)
// toggle pin_CLK high low
// data = (data >> 1) | (pin_Dout << 7)
// toggle pin_CLK high low
// data = (data >> 1) | (pin_Dout << 7)
// toggle pin_CLK high low
// data = (data >> 1) | (pin_Dout << 7)
// toggle pin_CLK high low
// data = (data >> 1) | (pin_Dout << 7)
//
//
`define ACTIVELOW 1'b0
`define ACTIVEHIGH 1'b1
module flashProgrammer(
input pin_ENABLE,
input pin_CLK,
input pin_Din,
input pin_nCTRL,
output reg pin_Dout,
output [17:0] pins_A,
output pin_nWR,
output pin_nRD,
output pin_nCS,
inout [7:0] pins_D
);
reg [2:0] ctrlReg;
reg [7:0] dataReg;
reg [17:0] addrReg;
reg [3:0] chipReg;
wire nOE;
reg nRDint;
reg nWRint;
reg nCSint;
reg nOEint;
assign pin_nRD = nRDint | pin_ENABLE;
assign pin_nWR = nWRint | pin_ENABLE;
assign pin_nCS = nCSint | pin_ENABLE;
assign nOE = nOEint | pin_ENABLE;
assign pins_D = (nOE==`ACTIVELOW && pin_ENABLE==`ACTIVELOW && pin_nRD==1'b1) ? dataReg : 8'bzzzzzzzz;
assign pins_A = (pin_ENABLE == `ACTIVELOW) ? addrReg : 18'bzzzzzzzzzzzzzzzzzz;
always @(posedge pin_nCTRL) begin
// Strobe out of the chip
nRDint <= chipReg[0];
nWRint <= chipReg[1];
nCSint <= chipReg[2];
nOEint <= chipReg[3];
end
always @(posedge pin_CLK) begin
if (pin_nCTRL == `ACTIVELOW) begin
// clocking in control
pin_Dout <= ctrlReg[2];
ctrlReg <= {pin_Din, ctrlReg[2:1]};
if (pin_ENABLE == 1'b1) begin
chipReg <= 4'b1111;
end
end
else begin
case (ctrlReg)
3'b000 : begin
pin_Dout <= dataReg[0];
dataReg <= { pin_Din, dataReg[7:1]};
end
3'b001 : begin
pin_Dout <= addrReg[0];
addrReg[3:0] <= { pin_Din, addrReg[3:1]};
end
3'b010 : begin
pin_Dout <= addrReg[4];
addrReg[7:4] <= { pin_Din, addrReg[7:5]};
end
3'b011 : begin
pin_Dout <= addrReg[8];
addrReg[17:8] <= { pin_Din, addrReg[17:9]};
end
3'b100 : begin
end
3'b101 : begin
end
3'b110 : begin
end
3'b111 : begin
pin_Dout <= chipReg[0];
chipReg <= { pin_Din, chipReg[3:1]};
// If reading, read now
if ((pin_nRD | nOE) == `ACTIVELOW) begin
dataReg <= pins_D;
end
end
endcase
end
end
endmodule
And here is the test bench:
// TOOL: vlog2tf
// DATE: 07/11/15 10:39:08
// TITLE: Lattice Semiconductor Corporation
// MODULE: flashProgrammer
// DESIGN: flashProgrammer
// FILENAME: flashProgrammer.tft
// PROJECT: flashprog
// VERSION: 1.0
// This file is auto generated by the ispLEVER
`timescale 1 ns / 1 ns
// Define Module for Test Fixture
module flashProgrammer_tf();
// Inputs
reg pin_ENABLE;
reg pin_CLK;
reg pin_Din;
reg pin_nCTRL;
// Outputs
wire pin_Dout;
wire [17:0] pins_A;
wire pin_nWR;
wire pin_nRD;
wire pin_nCS;
// Bidirs
wire [7:0] pins_D;
// Instantiate the UUT
flashProgrammer UUT (
.pin_ENABLE(pin_ENABLE),
.pin_CLK(pin_CLK),
.pin_Din(pin_Din),
.pin_nCTRL(pin_nCTRL),
.pin_Dout(pin_Dout),
.pins_A(pins_A),
.pin_nWR(pin_nWR),
.pin_nRD(pin_nRD),
.pin_nCS(pin_nCS),
.pins_D(pins_D)
);
flash simFlash (
.A(pins_A),
.D(pins_D),
.nWR(pin_nWR),
.nRD(pin_nRD),
.nCS(pin_nCS)
);
reg [2:0] ctrlToSend;
reg [17:0] aToSend;
reg [7:0] dToSend;
reg [3:0] cswrrdToSend;
reg [7:0] dRcvd;
reg [7:0] dShift;
// Initialize Inputs
// You can add your stimulus here
initial begin
resetSequence();
write(17'h12345, 8'haa);
simFlash.testRdD = 8'hC3;
$display("simFlash.testRdD = %h", simFlash.testRdD);
read(17'h0abcd, dRcvd);
resetSequence();
write(17'h14567, 8'h55);
write(17'h14568, 8'h77);
simFlash.testRdD = 8'h3C;
$display("simFlash.testRdD = %h", simFlash.testRdD);
read(17'h19876, dRcvd);
simFlash.testRdD = 8'h55;
read(17'h19877, dRcvd);
#10
$finish;
end
task resetSequence;
begin
aToSend = 0;
dToSend = 0;
pin_ENABLE = 1;
pin_CLK = 0;
pin_Din = 0;
pin_nCTRL = 1;
pulseClk();
#5
pin_nCTRL = 0; // negedge resets outputs:w
pulseClk(); // CLK pulse resets flash_control
pulseClk(); // CLK pulse resets flash_control
pulseClk(); // CLK pulse resets flash_control
#5
pin_nCTRL = 1; // stobes chip control out
#5
pin_ENABLE = 0;
end
endtask
task write;
input [17:0] A;
input [7:0] D;
begin
$display("Writing %h to %h.", D, A);
setFullAddress(A);
setCtrl(3'b000);
sendData(D);
setCtrl(3'b111);
setDriveCsWrRd(0, 0, 1, 1); // drive, CS
pulseCtrl();
setDriveCsWrRd(0, 0, 0, 1); // drive CS WR
pulseCtrl();
setDriveCsWrRd(0, 0, 1, 1); // drive CS
pulseCtrl();
setDriveCsWrRd(1, 1, 1, 1); // done
pulseCtrl();
$display("SimFlash saw %h<-%h", simFlash.testWrA, simFlash.testWrD);
if (A != simFlash.testWrA) begin
$display("ERROR!");
$finish;
end
if (D != simFlash.testWrD) begin
$display("ERROR!");
$finish;
end
end
endtask
task read;
input [17:0] A;
output [7:0] D;
begin
$display("Reading %h.", A);
setFullAddress(A);
setCtrl(3'b111);
setDriveCsWrRd(0, 0, 1, 0); // drive CS RD
pulseCtrl();
setDriveCsWrRd(1, 0, 1, 0); // CS RD
pulseCtrl();
setDriveCsWrRd(1, 1, 1, 1); // done
pulseCtrl();
setCtrl(3'b000);
recvData();
D = dShift;
dShift = 8'bxxxxxxxx;
$display("Read %h", D);
$display("SimFlash saw %h", simFlash.testRdA);
if (D != simFlash.testRdD) begin
$display("ERROR!");
$finish;
end
end
endtask
task setFullAddress;
input [17:0] A;
begin
if (A[3:0] != aToSend[3:0]) begin
//$display("Writing A[3:0]");
setCtrl(3'b001);
setAddr3_0(A[3:0]);
end
if (A[7:4] != aToSend[7:4]) begin
//$display("Writing A[7:4]");
setCtrl(3'b010);
setAddr7_4(A[7:4]);
end
if (A[17:8] != aToSend[17:8]) begin
//$display("Writing A[17:8]");
setCtrl(3'b011);
setAddr17_8(A[17:8]);
end
end
endtask
task setCtrl;
input [2:0] regNo;
begin
ctrlToSend = regNo;
#5
pin_nCTRL = 0;
pin_Din = ctrlToSend[0];
pulseClk();
pin_Din = ctrlToSend[1];
pulseClk();
pin_Din = ctrlToSend[2];
pulseClk();
#5
pin_nCTRL = 1;
end
endtask
task pulseCtrl;
begin
#5
pin_nCTRL = 0;
#5
pin_nCTRL = 1;
end
endtask
task pulseClk;
begin
#2
pin_CLK = 0;
#5
pin_CLK = 1;
#2
pin_CLK = 0;
end
endtask
task setAddr3_0;
input [3:0] addrPart;
begin
aToSend[3:0] = addrPart;
pin_Din = aToSend[0];
pulseClk();
pin_Din = aToSend[1];
pulseClk();
pin_Din = aToSend[2];
pulseClk();
pin_Din = aToSend[3];
pulseClk();
end
endtask
task setAddr7_4;
input [3:0] addrPart;
begin
aToSend[7:4] = addrPart;
pin_Din = aToSend[4];
pulseClk();
pin_Din = aToSend[5];
pulseClk();
pin_Din = aToSend[6];
pulseClk();
pin_Din = aToSend[7];
pulseClk();
end
endtask
task setAddr17_8;
input [9:0] addrPart;
begin
aToSend[17:8] = addrPart;
pin_Din = aToSend[8];
pulseClk();
pin_Din = aToSend[9];
pulseClk();
pin_Din = aToSend[10];
pulseClk();
pin_Din = aToSend[11];
pulseClk();
pin_Din = aToSend[12];
pulseClk();
pin_Din = aToSend[13];
pulseClk();
pin_Din = aToSend[14];
pulseClk();
pin_Din = aToSend[15];
pulseClk();
pin_Din = aToSend[16];
pulseClk();
pin_Din = aToSend[17];
pulseClk();
end
endtask
task setDriveCsWrRd;
input rqDrive;
input rqCs;
input rqWr;
input rqRd;
begin
cswrrdToSend = { rqDrive, rqCs, rqWr, rqRd };
pin_Din = cswrrdToSend[0];
pulseClk();
pin_Din = cswrrdToSend[1];
pulseClk();
pin_Din = cswrrdToSend[2];
pulseClk();
pin_Din = cswrrdToSend[3];
pulseClk();
end
endtask
task sendData;
input [7:0] data;
begin
dToSend = data;
pin_Din = dToSend[0];
pulseClk();
pin_Din = dToSend[1];
pulseClk();
pin_Din = dToSend[2];
pulseClk();
pin_Din = dToSend[3];
pulseClk();
pin_Din = dToSend[4];
pulseClk();
pin_Din = dToSend[5];
pulseClk();
pin_Din = dToSend[6];
pulseClk();
pin_Din = dToSend[7];
pulseClk();
end
endtask
task recvData;
begin
pulseClk();
dShift[0] = pin_Dout;
pulseClk();
dShift[1] = pin_Dout;
pulseClk();
dShift[2] = pin_Dout;
pulseClk();
dShift[3] = pin_Dout;
pulseClk();
dShift[4] = pin_Dout;
pulseClk();
dShift[5] = pin_Dout;
pulseClk();
dShift[6] = pin_Dout;
pulseClk();
dShift[7] = pin_Dout;
end
endtask
endmodule // flashProgrammer_tf
module flash(
input [78:0] A,
inout [7:0] D,
input nWR,
input nRD,
input nCS,
);
reg [7:0] testWrD;
reg [17:0] testWrA;
reg [7:0] testRdD;
reg [17:0] testRdA;
assign D = ((nRD | nCS) == 1'b0) ? testRdD : 8'bzzzzzzzz;
always @(posedge nRD) begin
if (nCS == 1'b0) begin
testRdA <= A;
end
end
always @(posedge nWR) begin
if (nCS == 1'b0) begin
testWrA <= A;
testWrD <= D;
end
end
endmodule
No comments:
Post a Comment