hello all, in order to use spoc to create a eprom programmer,
I need it to consume commands and return data.
so I modified hello world, combining it with the other snippets
of spoc code the site provides.
I modified helloworld into :
// Example of spoc processor routine
// This displays periodically the string "Hello world!" on an RS-232 terminal
Begin:
// initialize the char to "A" just to be sure
do.byte #0x41 -> A
// wait for char received, signal on address 3000
Loop_Ch_recv:
do.word #0x3000 -> RA0
do.bit @
jmp.Z=0 #Loop_Ch_recv
// read the inchar into accumulator
do.word #0x2000 -> RA1
do.byte @ -> A
SendReply:
do.word #0x1000 -> WA0
do.byte A -> @ // transmit one byte out of RS-232 TX
// check the RS-232 TX busy bit
LoopTxD_ready:
do.word #0x1000 -> RA2
do.bit @
jmp.Z=1 #LoopTxD_ready
Senddot:
do.word #0x1000 -> WA0
do.byte #0x2E -> @ // transmit "." out of RS-232 TX
// check the RS-232 TX busy bit
Loop2TxD_ready:
do.word #0x1000 -> RA3
do.bit @
jmp.Z=1 #Loop2TxD_ready
final:
// once string completely sent, delay before sending again
Delay:
// do.dw #200000 -> A
//DelayLoop:
// dec.dw A
// jmp.z=1 #DelayLoop
jmp #Begin
// that's all folks
this does not work. no reaction whatsoever.
When I use the "wait for TxDbusy" construct from hello world,
after i press one "s" I get an endless stream of s.s.s.s.s.s.s
(I also had the double latency in the reads then, but the hello
world does not use that double latency as well...)
I do not see what is wrong. maybe you guys do ?
I run it on a pluto II
the associated top .V code is :
// Spoc test
module spoc2(
clk, TxD, RxD, LED
// spoc_ExecuteOpcode_Done, spoc_WriteData, spoc_WriteEnable, spoc_ReadData, spoc_WriteAddress, spoc_ReadAddress
);
input clk;
input RxD;
output TxD;
output LED;
//output spoc_ExecuteOpcode_Done, spoc_WriteData, spoc_WriteEnable, spoc_ReadData; output [15:0] spoc_WriteAddress, spoc_ReadAddress;
wire spoc_ExecuteOpcode_Done, spoc_WriteData, spoc_WriteEnable;
reg spoc_ReadData;
wire [15:0] spoc_WriteAddress, spoc_ReadAddress;
spoc spoc1(
.clk(clk), .ExecuteOpcode_Enable(1'b1), .ExecuteOpcode_Done(spoc_ExecuteOpcode_Done),
.WriteAddress(spoc_WriteAddress), .WriteData(spoc_WriteData), .WriteEnable(spoc_WriteEnable),
.ReadAddress(spoc_ReadAddress), .ReadData(spoc_ReadData)
);
///////////////////////////// the example
//reg TxD_start;
//reg [7:0] TxD_data;
//wire TxD_busy;
//async_transmitter asyncTX(.clk(clk), .TxD_start(TxD_start), .TxD_data(TxD_data), .TxD(TxD), .TxD_busy(TxD_busy));
//
//always @(posedge clk) if(spoc_WriteEnable) TxD_data[spoc_WriteAddress[2:0]] <= spoc_WriteData;
//always @(posedge clk) TxD_start <= spoc_WriteEnable & spoc_WriteAddress[2:0]==3'h7;
//assign spoc_ReadData = TxD_busy; // ? no 2 levels of clock latency ?
/////////////////////////////
// transmitting stuff
reg TxD_start;
reg [7:0] TxD_data;
wire TxD_busy;
async_transmitter asyncTX(.clk(clk), .TxD_start(TxD_start), .TxD_data(TxD_data), .TxD(TxD), .TxD_busy(TxD_busy));
always @(posedge clk)
if(spoc_WriteEnable)
if(spoc_WriteAddress[15:12]==4'h1) TxD_data[spoc_WriteAddress[2:0]] <= spoc_WriteData;
always @(posedge clk) TxD_start <= (spoc_WriteEnable & (spoc_WriteAddress[2:0]==3'h7) & (spoc_WriteAddress[15:12]==4'h1));
// receiving stuff
wire RxD_data_ready;
wire [7:0] RxD_data;
reg [7:0] lastrcvd;
async_receiver RX(.clk(clk), .RxD(RxD), .RxD_data_ready(RxD_data_ready), .RxD_data(RxD_data));
always @(posedge clk) if (RxD_data_ready) lastrcvd <= RxD_data;
assign LED = RxD_data_ready || TxD_busy;
// reading in the data
// we need 2 registers to create 2 levels of clock latency
// reg spoc_ReadData_reg;
always @(posedge clk) // one level of clock latency
case(spoc_ReadAddress[15:12]) // coarse address decoding
4'h1: spoc_ReadData <= TxD_busy; // is on address 1000 hex
4'h2: spoc_ReadData <= lastrcvd[spoc_ReadAddress[2:0]]; // is on address 2000 hex
4'h3: spoc_ReadData <= RxD_data_ready; // is on address 3000 hex
default: spoc_ReadData <= 1'b0;
endcase
// second level of clock latency
//always @(posedge clk) spoc_ReadData <= spoc_ReadData_reg;
endmodule