Picoblaze on Mojo

Projects you are planning or working on with the Mojo
Post Reply
maurice
Posts: 8
Joined: November 2nd, 2013, 11:40 am

Picoblaze on Mojo

Post by maurice » November 2nd, 2013, 12:19 pm

Like others I looked at getting Zpuino to work on Mojo, as it does on the Papilio board. The main stumbling block seems to be that on Mojo the AVR manages the SPI flash , so its not directly accessible from the fpga. At least not without a little hardware modification or changing the AVR firmware.

So I thought that I should start small, with Picoblaze and see if I can get it to work. That way I might be able to use it as a bootloader for Zpuino, to load "sketches" through the serial interface. That should be possible, but the programs would not survive a power cycle since the SPI flash is the only persistent storage on the board.

I started with the Spartan 6 verilog version of Picoblaze. The whole cpu is in just one verilog file, plus you need a rom template that can be used for the program rom. I used the http://www.openpicide.org to prepare a Picoblaze program and create a program rom file from the Xilinx template. I just modified the Mojo base to include the Picoblaze core and rom. My first test program was to echo the serial port characters and also show their bit pattern on the Mojo leds. Here it is:

Code: Select all

; Echo serial port, send char bits to leds
; test program for mojo pico
;
; Outputs
LEDPORT	equ     0
TXPORT 	equ     1
; Inputs
STATUS 	equ	0
RXPORT 	equ     1
;
RXREADY	equ	0x01
TXREADY	equ	0x02
;
start:	LOAD	s1,0xFF
	OUT	s1, LEDPORT	; light all leds	
loop:	IN	s0, STATUS
	TEST	s0, RXREADY
	JUMP	Z, loop		; wait for ready
	IN	s1, RXPORT	; get character
	; echo
	CALL	putchar
	OUT	s1, LEDPORT
; if char is 0xD add lf (0xA)
	COMP	s1, 0x0D
	JUMP	NZ, loop
	LOAD	s1, 0x0A
	CALL	putchar
	JUMP	loop		; go for more
;
; Output char in s1
putchar:
	IN	s0, STATUS
	TEST	s0, TXREADY
	JUMP	Z, putchar
	OUT	s1, TXPORT
	RET	
;
; delay ~1s		
delay:	LOAD 	s2, 0x30
	LOAD 	s1, 0xE2
	LOAD   	s0, 0x50
dloop: 	SUB	s0, 1
	SUBC    s1, 0
	SUBC 	s2, 0
	JUMP    NZ, dloop
	RET
;	
	org     0x3ff
isr:	JUMP 	isr
And my Mojo top looks like this:

Code: Select all

module mojo_top(
    input clk,
    input rst_n,
    input cclk,
    output[7:0]led,
    output spi_miso,
    input spi_ss,
    input spi_mosi,
    input spi_sck,
    output [3:0] spi_channel,
    input avr_tx,
    output avr_rx,
    input avr_rx_busy
    );

wire rst = ~rst_n;

assign spi_miso = 1'bz;
assign avr_rx = 1'bz;
assign spi_channel = 4'bzzzz;

// Serial port on avr interface
reg [7:0] tx_data;
wire new_tx_data;
wire tx_busy;
wire [7:0] rx_data;
wire new_rx_data;

// Mojo board leds
reg [7:0] led;

// Mojo fpga-avr interface
avr_interface avr_interface (
    .clk(clk),
    .rst(rst),
    .cclk(cclk),
    .spi_miso(spi_miso),
    .spi_mosi(spi_mosi),
    .spi_sck(spi_sck),
    .spi_ss(spi_ss),
    .spi_channel(spi_channel),
    .tx(avr_rx), // FPGA tx goes to AVR rx
    .rx(avr_tx),
    .channel(4'd15), // invalid channel disables the ADC
    .new_sample(),
    .sample(),
    .sample_channel(),
    .tx_data(tx_data),
    .new_tx_data(new_tx_data),
    .tx_busy(tx_busy),
    .tx_block(avr_rx_busy),
    .rx_data(rx_data),
    .new_rx_data(new_rx_data)
);

// Picoblaze connections

wire [11:0] address;
wire [17:0] instruction;
wire [7:0] out_port;
reg [7:0] in_port;
wire write_strobe;
wire read_strobe;
wire [7:0] port_id;
wire enable;


// Picoblaze (kcpsm6) from Xilinx

// Program rom memory 	
echo mem (address,
		instruction,
       enable,
       clk);
		 
assign enable = bram_enable;		 
		 
// CPU
kcpsm6 cpu (address, instruction, bram_enable, 
	in_port, out_port, port_id, write_strobe, k_write_strobe, read_strobe, 
	interrupt, interrupt_ack, sleep, reset, clk) ;

// Picoblaze Mojo IO subsystem

// IO port definitions
/* input
	 0 - uart status (read ready in low bit)
    1 - uart read data
  output
    0 - leds
	 1 - uart write data
*/


// IO writes
always @(posedge write_strobe) begin
	case (port_id)
	0: begin
		led <= out_port;
	end
	1: begin
		tx_data <= out_port;
		end
	default: begin

	end

	endcase

end  // io write

// IO reads
reg rx_empty;
reg rx_ready;

always @(posedge read_strobe) begin
	rx_empty = 0;
	case (port_id)
	0: begin
		in_port <= { 6'b000000, !tx_busy, rx_ready };
	end
	1: begin
		in_port <= rx_data;
		rx_empty = 1;
	end
	endcase
end //io read

assign new_tx_data = (port_id == 1)? write_strobe & !tx_busy : 1'b0;

always @(posedge clk) begin
	if (new_rx_data) begin
	rx_ready = 1;
	end else begin
	rx_ready = (avr_rx_busy) ?  0 : rx_ready & !rx_empty;
	end
end

endmodule
The only other modification needed was to set the avr baud rate to 115200 by changing the timing constants in the serial rx and tx to 434.

I hope this helps someone. At least now I have a little cpu on the Mojo, even though its rather restricted. If anyone needs more details I'll be glad to supply them.

Post Reply