有这样写VERILOG风格吗?类似风格好像我没有见过别人写过。我只是为了简洁,写得快,就有了这种FSM串行序列执行的的写法。感觉难度介于汇编和C之间。运行效果也很好,就暂时没有进行优化和替换。
/*
module tb_cfg_FSM;
reg clk,rst,valid;
reg [23:0] ins ;
initial begin
{clk,rst,valid}=0;
rst = 1;
#100 rst = 0;
#100000; $finish ;
end
CFG_FSM cfg_FSM (
.clk(clk),
.rst(rst),
.valid(valid) ,
.ready(ready),
.ins(ins),
.error(error),
.spi_mosi(spi_mosi),
.spi_clk(spi_clk),
.spi_csn(spi_csn),
.spi_miso(spi_miso)
);
endmodule
*/
module CFG_FSM #(parameter FRQ = 100*1000*1000)(
input clk,rst,
input valid ,
output reg ready,
input [23:0] ins,
output reg error,
output [7:0]dout,
output spi_mosi,spi_clk,spi_csn,
input spi_miso
);
reg [7:0] st ;
reg [23:0] insr ;
reg [2:0] op_type ;
//0 write reg
//1 read reg
//2 wait time
//3 wait a bit
always @ (posedge clk)if (st==3)begin
if (insr[23]==1) op_type = 0; // write
else case (insr[22:20])
0 : op_type = 1 ;
1 : op_type = 2 ;
2 : op_type = 3 ;
3 : op_type = 4 ;
default op_type = 'hx ;
endcase end
wire [23:0] cmd24bit = {insr[23],3'b000,insr[19:0]};
reg [15:0] ms_tmr ;
wire ms_of = ms_tmr == (FRQ/1000-1) ;
// wire ms_of = ms_tmr == (10-1) ;
reg ms_state = 0 ;
always@*case (st) 121,130,131,132,133,134,135 ,136: ms_state=1;default ms_state=0;endcase
always @ (posedge clk) if (ms_state)ms_tmr<= ( ms_of ) ?0 :1+ms_tmr;else ms_tmr<=0;
//always@(posedge clk) if (ms_state)ms_tmr<= 1+ms_tmr;else ms_tmr<=0;
reg [15:0] ms_cnt;
always @ (posedge clk) if (ms_state) ms_cnt<=(ms_of)?ms_cnt+1:ms_cnt; else ms_cnt<=0;
reg FSM_valid ;
reg [7:0] read_value ;
wire[7:0] FSM_dout ;
wire if_n_zero = (read_value & (1<<insr[2:0])) !=0 ;
always @ (posedge clk)
if (rst) st<=0;else case (st)
0:begin ready<=0; FSM_valid<=0;st<=1;error<=0;end
1:if (valid) begin ready<=0; error<=0;st<=2;end
2:begin st<=3;insr<=ins;end //store this instruction
3:st<=4; //decode
4:case (op_type)
0:st<=100;// write reg
1:st<=110;// read reg
2:st<=120;// wait ms
3:st<=130;// check a bit
default st<=0;
endcase
100: begin st<=101;FSM_valid<=1;end
101: begin FSM_valid<=0;st<=102;end
102:st<=103;
103:st<=104;
104: if (FSM_ready) st<=105;
105: st<=106;
106: st<=200; // endof write reg
110: begin st<=111;FSM_valid<=1;end
111: begin FSM_valid <=0; st<=112; end
112: st <= 113 ;
113: st <= 114 ;
114: if (FSM_ready) st<=115;
115: begin read_value <= FSM_dout ; st <= 116 ; end
116: st <= 200 ; // endof read reg
120: st<=121;
121: if (ms_cnt[15:0]==insr[15:0]) st<=122;
122: st <= 123 ;
123: st <= 200; // wait time
130: begin st<=131;FSM_valid<=1;end
131: begin FSM_valid <= 0 ; st<=132;end
132: st<=133;
133: st<=134;
134: if (FSM_ready) st<=135; else if (ms_cnt[15:0] >= 2000 ) st<=160;
135: begin read_value <= FSM_dout ; st <= 136; end
136: case ({insr[7],if_n_zero})2'b00 ,2'b11: st<=137;default st<=130 ;endcase
137: st<=200 ; // return ok, check a bit and wait
160: begin error<=1;st<=1;end
200: begin ready<=1;st<=1;end
default st<=0;
endcase
assign dout = FSM_dout ;
spi_ad9361_if #( .cnt_bit(3) ) spi_ad9361_if (
.clk ( clk ),
.rst ( rst ),
.spi_mosi ( spi_mosi ),
.spi_clk ( spi_clk),
.spi_csn ( spi_csn),
.spi_miso ( spi_miso ),
.din ( cmd24bit ),
.dout ( FSM_dout ) ,
.valid ( FSM_valid ) ,
.ready ( FSM_ready )
);
endmodule