Dual-picoblaze sender-receiver
From Gezel2
This example illustrates two picoblaze cores communicating through two port-mapped channels. The picoblaze instruction-set simulator is from the [kpicosim project].
ipblock mypico_A (
out port_id : ns(8);
out write_strobe : ns(1);
out read_strobe : ns(1);
out out_port : ns(8);
in in_port : ns(8);
in interrupt : ns(1);
out interrupt_ack : ns(1);
in reset : ns(1);
in clk : ns(1)) {
iptype "picoblaze";
ipparm "exec=SENDER.DEC";
}
ipblock mypico_B (
out port_id : ns(8);
out write_strobe : ns(1);
out read_strobe : ns(1);
out out_port : ns(8);
in in_port : ns(8);
in interrupt : ns(1);
out interrupt_ack : ns(1);
in reset : ns(1);
in clk : ns(1)) {
iptype "picoblaze";
ipparm "exec=RECEIVER.DEC";
}
dp mappedreg_60(in d : ns(8);
in adr : ns(8);
in ws : ns(1);
out do : ns(8)) {
reg r : ns(8);
reg f : ns(1);
always {
f = ws;
r = ws ? ((adr == 0x60) ? d : r) : r;
do = r;
}
sfg show {
$display($cycle, ": ", $dp, " ", r);
}
sfg idle { }
}
fsm f_mappedreg_60(mappedreg_60) {
initial s0;
@s0 if (f) then (show) -> s0;
else (idle) -> s0;
}
dp mappedreg_60_b : mappedreg_60
dp top {
/* Picoblaze "A" ports */
sig pbA_port_id : ns(8); // address
sig pbA_ws, pbA_rs : ns(1); // read, write strobes
sig pbA_output, pbA_input : ns(8); // output, input ports
sig pbA_int, pbA_int_ack : ns(1); // interrupt, and interrupt ack port
sig pbA_rst, pbA_clk : ns(1); // reset and clk ports (not used in GEZEL, but
// needed to correctly translated to VHDL)
/* Picoblaze "B" ports */
sig pbB_port_id : ns(8); // address
sig pbB_ws, pbB_rs : ns(1); // read, write strobes
sig pbB_output, pbB_input : ns(8); // output, input ports
sig pbB_int, pbB_int_ack : ns(1); // interrupt, and interrupt ack port
sig pbB_rst, pbB_clk : ns(1); // reset and clk ports (not used in GEZEL, but
// needed to correctly translated to VHDL)
/* Memory mapped registers */
sig pbA_to_pbB : ns(8);
sig pbB_to_pbA : ns(8);
/* Datapath/Module instantiations */
use mypico_A (pbA_port_id, pbA_ws, pbA_rs,
pbA_output, pbA_input,
pbA_int, pbA_int_ack,
pbA_rst, pbA_clk);
use mypico_B (pbB_port_id, pbB_ws, pbB_rs,
pbB_output, pbB_input,
pbB_int, pbB_int_ack,
pbB_rst, pbB_clk);
use mappedreg_60 (pbA_output, pbA_port_id, pbA_ws, pbA_to_pbB);
use mappedreg_60_b(pbB_output, pbB_port_id, pbB_ws, pbB_to_pbA);
always {
pbB_input = pbA_to_pbB;
pbA_input = pbB_to_pbA;
pbA_int = pbB_int = 0; // not using interrupts
// The following "clk" and "rst" signals are not used in the
// GEZEL simulation, so we just set them to a constant value
pbA_rst = pbB_rst = pbA_clk = pbB_clk = 0;
}
}
system S {
top;
}
receiver.psm
; ENABLE INTERRUPT
LOAD SA,00
LOAD SA,00
LOAD SA,00
LOAD SA,00
LOAD SA,00 ; STARTUP DELAY
INIT: INPUT SA, 20
COMPARE SA,00
JUMP Z, INIT
OUTPUT SA, 60
ACK2: INPUT SA, 20
COMPARE SA,00
JUMP NZ, ACK2
OUTPUT SA, 60
JUMP INIT
sender.psm
; ENABLE INTERRUPT
INIT: LOAD SA,01 ;INITIAL VALUE IS 15
LOOP: OUTPUT SA,60 ;SEND IT OUT ON PORT 60
ACK1: INPUT SB,20
COMPARE SB,00 ;READ RESPONSE
JUMP Z,ACK1
LOAD SB,00
OUTPUT SB,60 ;SEND 2nd half of handshake
ACK2: INPUT SB,20 ;READ RESPONSE
COMPARE SB,00
JUMP NZ,ACK2
ADD SA,01
COMPARE SA,00 ;make sure we don't use 0 as a data value
JUMP NZ,LOOP
ADD SA,01
JUMP LOOP ;KEEP DOING IT FOREVER
Simulation Output
To simulate this program, the sender.psm and receiver.psm must be assembled first using the picoblaze assembler KCPSM3.EXE. The resulting .DEC files are used by the cosimulation to insitialize the program memory for each picoblaze.
>gplatform -c 1000 pb.fdl picosystem: loading executable [SENDER.DEC] (RESET EVENT) picosystem: loading executable [RECEIVER.DEC] (RESET EVENT) 4: mappedreg_60 1/1 18: mappedreg_60_b 1/1 32: mappedreg_60 0/0 44: mappedreg_60_b 0/0 58: mappedreg_60 2/2 66: mappedreg_60_b 2/2 80: mappedreg_60 0/0 92: mappedreg_60_b 0/0 106: mappedreg_60 3/3 114: mappedreg_60_b 3/3 128: mappedreg_60 0/0 140: mappedreg_60_b 0/0 154: mappedreg_60 4/4 162: mappedreg_60_b 4/4 176: mappedreg_60 0/0 188: mappedreg_60_b 0/0 202: mappedreg_60 5/5 210: mappedreg_60_b 5/5 224: mappedreg_60 0/0 236: mappedreg_60_b 0/0 250: mappedreg_60 6/6 258: mappedreg_60_b 6/6 272: mappedreg_60 0/0 284: mappedreg_60_b 0/0 298: mappedreg_60 7/7 306: mappedreg_60_b 7/7 320: mappedreg_60 0/0 332: mappedreg_60_b 0/0 346: mappedreg_60 8/8 354: mappedreg_60_b 8/8 368: mappedreg_60 0/0 380: mappedreg_60_b 0/0 394: mappedreg_60 9/9 402: mappedreg_60_b 9/9 416: mappedreg_60 0/0 428: mappedreg_60_b 0/0 442: mappedreg_60 a/a 450: mappedreg_60_b a/a 464: mappedreg_60 0/0 476: mappedreg_60_b 0/0 490: mappedreg_60 b/b 498: mappedreg_60_b b/b 512: mappedreg_60 0/0 524: mappedreg_60_b 0/0 538: mappedreg_60 c/c 546: mappedreg_60_b c/c 560: mappedreg_60 0/0 572: mappedreg_60_b 0/0 586: mappedreg_60 d/d 594: mappedreg_60_b d/d 608: mappedreg_60 0/0 620: mappedreg_60_b 0/0 634: mappedreg_60 e/e 642: mappedreg_60_b e/e 656: mappedreg_60 0/0 668: mappedreg_60_b 0/0 682: mappedreg_60 f/f 690: mappedreg_60_b f/f 704: mappedreg_60 0/0 716: mappedreg_60_b 0/0 730: mappedreg_60 10/10 738: mappedreg_60_b 10/10 752: mappedreg_60 0/0 764: mappedreg_60_b 0/0 778: mappedreg_60 11/11 786: mappedreg_60_b 11/11 800: mappedreg_60 0/0 812: mappedreg_60_b 0/0 826: mappedreg_60 12/12 834: mappedreg_60_b 12/12 848: mappedreg_60 0/0 860: mappedreg_60_b 0/0 874: mappedreg_60 13/13 882: mappedreg_60_b 13/13 896: mappedreg_60 0/0 908: mappedreg_60_b 0/0 922: mappedreg_60 14/14 930: mappedreg_60_b 14/14 944: mappedreg_60 0/0 956: mappedreg_60_b 0/0 970: mappedreg_60 15/15 978: mappedreg_60_b 15/15 992: mappedreg_60 0/0 Total Cycles: 1000
