Skip to content

Commit

Permalink
Initial work on bitstream programming. Not yet tested in hardware sin…
Browse files Browse the repository at this point in the history
…ce it doesn't fit on my Zybo. Need to grab more JTAG dongles and test on an XC7A100T
azonenberg committed Jun 14, 2017
1 parent ba95711 commit 7ba4c26
Showing 2 changed files with 84 additions and 17 deletions.
35 changes: 22 additions & 13 deletions hdl/xc2c-model/XC2CDevice.v
Original file line number Diff line number Diff line change
@@ -124,8 +124,7 @@ 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'b0}}; //default initial value
ram_bitstream[i] <= {SHREG_WIDTH{1'b1}}; //copied from blank EEPROM = all 1s
end

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -140,10 +139,26 @@ module XC2CDevice(
wire[ADDR_BITS-1:0] config_read_addr;
reg[SHREG_WIDTH-1:0] config_read_data = 0;

//Read the EEPROM
wire config_write_en;
wire[ADDR_BITS-1:0] config_write_addr;
wire[SHREG_WIDTH-1:0] config_write_data;

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

if(config_write_en)
ram_bitstream[config_write_addr] <= config_write_data;

//Wipe the config memory
//TODO: pipeline this or are we OK in one cycle?
//If we go multicycle, how do we handle this with no clock? Real chip is self-timed internally
if(config_erase) begin
for(i=0; i<MEM_DEPTH; i=i+1)
ram_bitstream[i] <= {SHREG_WIDTH{1'b1}};
end

end

XC2CJTAG #(
@@ -161,20 +176,14 @@ module XC2CDevice(
.config_read_addr(config_read_addr),
.config_read_data(config_read_data),

.config_write_en(config_write_en),
.config_write_addr(config_write_addr),
.config_write_data(config_write_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
66 changes: 62 additions & 4 deletions hdl/xc2c-model/XC2CJTAG.v
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@ module XC2CJTAG(
tdi, tms, tck, tdo,
config_erase,
config_read_addr, config_read_data,
config_write_en, config_write_addr, config_write_data,

debug_led, debug_gpio);

@@ -49,9 +50,14 @@ module XC2CJTAG(
//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)

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 config_write_en = 0;
output reg[ADDR_BITS-1:0] config_write_addr = 0;
output reg[SHREG_WIDTH-1:0] config_write_data = 0;

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

@@ -275,6 +281,12 @@ module XC2CJTAG(
configured <= 0;
end

//DEBUG: declare us configured as soon as we get a PROGRAM instruction
//TODO: check DONE / transfer bits first
if(ir_shreg == INST_ISC_PROGRAM) begin
configured <= 1;
end

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

end //end STATE_UPDATE_IR
@@ -487,6 +499,51 @@ module XC2CJTAG(

end

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Config memory writes

reg[SHREG_WIDTH + ADDR_BITS - 1 : 0] isc_write_shreg = 0;

//Gray coded write address: left N bits of the shift register
wire[ADDR_BITS-1:0] isc_write_addr_gray = isc_write_shreg[SHREG_WIDTH +: ADDR_BITS];

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

always @(posedge tck) begin

config_write_en <= 0;

if(ir == INST_ISC_PROGRAM) begin
case(state)

//Capture data is ignored
STATE_CAPTURE_DR: begin
isc_write_shreg <= 0;
end //end STATE_CAPTURE_DR

//Read the new bitstream
STATE_SHIFT_DR: begin
isc_write_shreg <= {tdi, isc_write_shreg[SHREG_WIDTH + ADDR_BITS -1 : 1]};
end //end STATE_SHIFT_DR

//Update: commit the write to bitstream
STATE_UPDATE_DR: begin
config_write_en <= 1;
config_write_addr <= isc_write_addr_normal;
config_write_data <= isc_write_shreg[SHREG_WIDTH-1 : 0];
end //end STATE_UPDATE_DR

endcase
end

end

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

@@ -501,9 +558,10 @@ module XC2CJTAG(
//DR stuff
else if(state == STATE_SHIFT_DR) begin
case(ir)
INST_BYPASS: tdo <= bypass_shreg;
INST_IDCODE: tdo <= idcode_shreg[0];
INST_ISC_READ: tdo <= isc_read_shreg[0];
INST_BYPASS: tdo <= bypass_shreg;
INST_IDCODE: tdo <= idcode_shreg[0];
INST_ISC_READ: tdo <= isc_read_shreg[0];
INST_ISC_PROGRAM: tdo <= isc_write_shreg[0];
endcase
end

0 comments on commit 7ba4c26

Please sign in to comment.