I've been getting a real education in working with FPGA's the last month or so. Perhaps someone could help me work through the way to handle this problem. Hope this isn't too long a post...
Here is a simplified example of what I've been working on. It outputs a byte serially at a slow clock speed.
module doprocess(clk,start,datToSend,done, clkB, sbit);
input clk; // 50 mhz system clock
input start; // signal to reset timer, load byte to shift reg
output done; // set when all bits have been shifted
output clkB; // slow clock synched with serial out
output sbit=shiftreg[7]; // bit being shifted out (msb first)
input [7:0]datToSend; // value to be shifted out
reg [24:0]tmr; // generate slow clock from 50mhz clock
always @(posedge clk)
tmr<=tmr+1;
reg [3:0]cnt; // count to 8 to shift out one byte
// flags when cnt outputs 8 bits
reg cnt_elapsed; always@(posedge clk)cnt_elapsed<= (cnt[3]==1'b1);
assign clkB = tmr[24]; // slower clock
assign done=cnt_elapsed;
reg [7:0] shiftreg;
// notice clocked by slow clock but using start which is from a faster domain
always @(posedge clkB or posedge start)begin
if(start==1'b1)begin
shiftreg<= datToSend;
cnt<=0;
end
else
begin
cnt<=cnt+1;
shiftreg<={shiftreg[6:0],1'b0};
end
end
endmodule
I can load this in a demo board, use switches for data in, LEDS for signals out and it does what it's supposed to, the slow clock flashes on led2, led3 flashes on or off reading off each switch, and led1 comes on when all 8 bits are done:
module top(input clk, //... etc. etc.
doprocess doprocessinst(clk,switches[9],switches[7:0],led1,led2,led3);
endmodule
The challenge for me is how to best implement a controller for this. I have read the links in the crossing domains example project and looked at the examples, but I'm having trouble trying to figure out how to actually implement the techniques in this design. I've tried some of the examples but haven't had success yet. Here is the code that I want to be able to do (of course it won't work because it crosses domains):
module top(.....
.
.
doProcess doprocessinst clk,startprocess, datToSend,processdone,led2,led3);
cmdProcess cmdprocessinst(clk,switches[9],switches[7:0], startprocess, datToSend,processdone,led1);
endmodule
module cmdProcess(
input clk,
input startcmd, // flag from some other source telling us to start sending datinput (i.e. a third possible domain)
input [7:0]datinput, // byte (or bytes) being sent to us to be shifted out
output reg startprocess, // flag to tell doProcess to start shifting
output reg [7:0]datoutput, // byte to send to doProcess
input processdone, // flag from doProcess telling us the byte's done
output reg cmddone // flag we raise after all bytes have been done
);
reg [4:0]fstate;
reg [4:0]reg_fstate;
always @(posedge clk)
fstate <= reg_fstate;
// clock problems 3 domains warring for mastery
always @(posedge clk or negedge startcmd)begin
if(startcmd==1'b0)
reg_fstate<=1;
else
case(fstate)
0:begin
startprocess<=1; // hold this high till ready
end
1:begin
startprocess<=1;
datoutput<=datinput;
reg_fstate<=2;
end
2:begin
startprocess<=0; // let shifter start
if(processdone) begin
reg_fstate<=3;
end
else
reg_fstate<=2;
end
// can repeat here to do multiple bytes
3:begin
cmddone<=1'b1; // tell master we are done
end
endcase
end
endmodule
The problems begin with trying to cross startprocess and processdone
I will keep working on this trying more of the techniques, but if someone could share an example of how to deal with this type of example it would be great. Thanks