Skip to content

Commit

Permalink
Continued XC2CDevice model. Can now enumerate the device, read the ID…
Browse files Browse the repository at this point in the history
… code/instruction capture state, erase, and read back. Next up, programming
azonenberg committed Jun 14, 2017
1 parent 216ad0e commit ba95711
Showing 2 changed files with 127 additions and 6 deletions.
48 changes: 46 additions & 2 deletions hdl/xc2c-model/XC2CDevice.v
Original file line number Diff line number Diff line change
@@ -65,8 +65,24 @@ module XC2CDevice(
end
endfunction

function integer ConfigMemoryAbits;
input[15:0] cells;
begin
case(cells)
32: ConfigMemoryAbits = 6;
64: ConfigMemoryAbits = 7;
128: ConfigMemoryAbits = 7;
256: ConfigMemoryAbits = 7;
384: ConfigMemoryAbits = 7;
512: ConfigMemoryAbits = 8;
default: ConfigMemoryAbits = 0;
endcase
end
endfunction

localparam SHREG_WIDTH = ConfigMemoryWidth(MACROCELLS);
localparam MEM_DEPTH = ConfigMemoryDepth(MACROCELLS);
localparam ADDR_BITS = ConfigMemoryAbits(MACROCELLS);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Sanity checks
@@ -108,7 +124,8 @@ module XC2CDevice(
integer i;
initial begin
for(i=0; i<MEM_DEPTH; i=i+1)
ram_bitstream[i] <= {SHREG_WIDTH{1'b1}}; //copied from blank EEPROM = all 1s
//ram_bitstream[i] <= {SHREG_WIDTH{1'b1}}; //copied from blank EEPROM = all 1s
ram_bitstream[i] <= {SHREG_WIDTH{1'b0}}; //default initial value
end

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -119,19 +136,46 @@ module XC2CDevice(
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// JTAG stuff

wire config_erase;
wire[ADDR_BITS-1:0] config_read_addr;
reg[SHREG_WIDTH-1:0] config_read_data = 0;

//Read the EEPROM
//TODO: add read enable?
always @(posedge jtag_tck) begin
config_read_data <= ram_bitstream[config_read_addr];
end

XC2CJTAG #(
.MACROCELLS(MACROCELLS),
.PACKAGE(PACKAGE)
.PACKAGE(PACKAGE),
.SHREG_WIDTH(SHREG_WIDTH),
.ADDR_BITS(ADDR_BITS)
) jtag (
.tdi(jtag_tdi),
.tdo(jtag_tdo),
.tms(jtag_tms),
.tck(jtag_tck),

.config_erase(config_erase),
.config_read_addr(config_read_addr),
.config_read_data(config_read_data),

.debug_led(debug_led),
.debug_gpio(debug_gpio)
);

always @(posedge jtag_tck) begin

//Wipe the config memory when asked
//TODO: pipeline this or are we OK in one cycle?
if(config_erase) begin
for(i=0; i<MEM_DEPTH; i=i+1)
ram_bitstream[i] <= {SHREG_WIDTH{1'b1}};
end

end

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// The actual CPLD function blocks

85 changes: 81 additions & 4 deletions hdl/xc2c-model/XC2CJTAG.v
Original file line number Diff line number Diff line change
@@ -20,7 +20,12 @@
/**
@brief JTAG stuff for an XC2C-series device
*/
module XC2CJTAG(tdi, tms, tck, tdo, debug_led, debug_gpio);
module XC2CJTAG(
tdi, tms, tck, tdo,
config_erase,
config_read_addr, config_read_data,

debug_led, debug_gpio);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Device configuration
@@ -29,6 +34,10 @@ module XC2CJTAG(tdi, tms, tck, tdo, debug_led, debug_gpio);

parameter PACKAGE = "QFG32"; //Package code (lead-free G assumed)

parameter SHREG_WIDTH = 1; //ISC shift register width

parameter ADDR_BITS = 1; //Bits in ISC address shift register

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// I/Os

@@ -37,6 +46,12 @@ module XC2CJTAG(tdi, tms, tck, tdo, debug_led, debug_gpio);
input wire tck;
output reg tdo;

//Status signals to the configuration memory
output reg config_erase = 0; //Erases all config memory
//This takes 100 ms IRL but for now we'll model it instantly
output reg[ADDR_BITS-1:0] config_read_addr = 0; //Address for reading the bitstream (real, not gray code)
input wire[SHREG_WIDTH-1:0] config_read_data;

output reg[3:0] debug_led = 0;
output reg[7:0] debug_gpio = 0;

@@ -219,6 +234,8 @@ module XC2CJTAG(tdi, tms, tck, tdo, debug_led, debug_gpio);
//Instruction loading and capture
always @(posedge tck) begin

config_erase <= 0;

case(state)

//Reset instruction to IDCODE upon reset
@@ -243,7 +260,23 @@ module XC2CJTAG(tdi, tms, tck, tdo, debug_led, debug_gpio);

//Done, save the new IR
STATE_UPDATE_IR: begin
ir <= ir_shreg;
ir <= ir_shreg;

//If we're entering/exiting ISC mode, set the ISC bits appropriately
//TODO: support OTF mode
if(ir_shreg == INST_ISC_ENABLE)
isc_enabled <= 1;
if(ir_shreg == INST_ISC_DISABLE)
isc_enabled <= 0;

//Wipe config memory when we get an ERASE instruction
if(ir_shreg == INST_ISC_ERASE) begin
config_erase <= 1;
configured <= 0;
end

//TODO: copy EEPROM to RAM when we get an ISC_INIT command

end //end STATE_UPDATE_IR

endcase
@@ -400,7 +433,7 @@ module XC2CJTAG(tdi, tms, tck, tdo, debug_led, debug_gpio);
idcode_shreg <= idcode;
end //end STATE_CAPTURE_DR

//Loading a new IR
//Read the IDCODE
STATE_SHIFT_DR: begin
idcode_shreg <= {tdi, idcode_shreg[31:1]};
end //end STATE_SHIFT_DR
@@ -411,6 +444,49 @@ module XC2CJTAG(tdi, tms, tck, tdo, debug_led, debug_gpio);

end

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Config memory read

reg[SHREG_WIDTH-1:0] isc_read_shreg = 0;

//New value for the read shreg
wire[SHREG_WIDTH-1:0] isc_read_shreg_adv = {tdi, isc_read_shreg[SHREG_WIDTH-1:1]};

//Gray coded read address: left N bits of the shift register
wire[ADDR_BITS-1:0] isc_read_addr_gray = isc_read_shreg_adv[SHREG_WIDTH-1 : SHREG_WIDTH-ADDR_BITS];

//Convert Gray code to normal
reg[ADDR_BITS-1:0] isc_read_addr_normal;
integer i;
always @(*) begin
isc_read_addr_normal[ADDR_BITS-1] <= isc_read_addr_gray[ADDR_BITS-1];
for(i=ADDR_BITS-2; i>=0; i=i-1)
isc_read_addr_normal[i] <= isc_read_addr_gray[i] ^ isc_read_addr_normal[i+1];
end

always @(posedge tck) begin

case(state)

//Load the data that we read
STATE_CAPTURE_DR: begin
isc_read_shreg <= config_read_data;
end //end STATE_CAPTURE_DR

//Actual readout happens here
STATE_SHIFT_DR: begin
isc_read_shreg <= isc_read_shreg_adv;
end //end STATE_SHIFT_DR

//Update: save the de-Gray-ified read address
STATE_UPDATE_DR: begin
config_read_addr <= isc_read_addr_normal;
end //end STATE_UPDATE_DR

endcase

end

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TDO muxing

@@ -427,6 +503,7 @@ module XC2CJTAG(tdi, tms, tck, tdo, debug_led, debug_gpio);
case(ir)
INST_BYPASS: tdo <= bypass_shreg;
INST_IDCODE: tdo <= idcode_shreg[0];
INST_ISC_READ: tdo <= isc_read_shreg[0];
endcase
end

@@ -439,7 +516,7 @@ module XC2CJTAG(tdi, tms, tck, tdo, debug_led, debug_gpio);
//7:0 = pmod_c[3:0]
always @(*) begin
debug_gpio <= 0;
debug_gpio[0] <= (ir == INST_IDCODE);
debug_gpio[0] <= (ir == INST_ISC_READ);
debug_gpio[1] <= (ir == INST_BYPASS);
end

0 comments on commit ba95711

Please sign in to comment.