暫く更新をしてなかったが、少しずつ進めてはいる。16F648は前にも書いたけど、ペリフェラルがてんこ盛りで、I/Oはマルチプレックスされていて、面倒くさいことこの上ない。やっと、シンタクスエラーとかがとれて、PORTA、PORTB、Timer0のヴェリフィケーションが(概ね)終了。Timer1のデバッグ中。プリスケーラのロジックがおかしかったのを修正して、ポーリングでの動作までは確認した。
ちょっと飽きてきたので、とりあえず端折った、USARTを考えている。受信バッファにFIFOがあるので、サブモジュールとして作ってみる。ていうか、Synchronous(同期式)FIFOだったら、webを探せば、何かあるだろうと思い、サーチしてみた。こんなのが見つかった。手堅い実装だが、論理合成することを考えるとイマイチな気がするので、少し考えてみた(例によってソースコードは最後に)。ちょっとだけ、工夫をしたのは、リード/ライトが同時に起きる場合。FIFOがFULLな状態でも、リード/ライトが同時に起きる場合は、ライトができてしかるべきである。一応、単体で検証してみるが、問題ないようである。リード/ライトをランダムに起こすようにして、いわゆるランダム検証っぽくしてみたりして(笑)。
---
本日の御託
いわゆる「帰るコール」をしたら、家内が沈みがちので、帰る途中のショッピングモールに出ていた、「はまコロ」なる、コロッケを土産に買ってみた。小ぶりながら、税込み105円とちょっとお高めだった。ただのビーフ・ポテトコロッケだが、確かに旨かった。家内も「プチ・ハッピ~」。(お手軽すぎ。笑)
1 //
2 // Synchronous FIFO
3 // (c)2007 BakaOyaji
4
5 // SFIFO_ADDR_WIDTH is for the width of internal memory
6 // i.e. 4 makes 16 deep fifo
7 // and it must be >= 1
8 `define SFIFO_ADDR_WIDTH 1
9
10 `define SFIFO_WIDTH 9
11
12 module sfifo(
13 input clk_i,
14 input por_i,
15 input we_i,
16 input [(`SFIFO_WIDTH-1):0] data_i,
17 output full_o,
18
19 input re_i,
20 output [(`SFIFO_WIDTH-1):0] data_o,
21 output empty_o
22 );
23
24 reg [`SFIFO_ADDR_WIDTH :0] wr_ptr, rd_ptr;
25 reg [(`SFIFO_WIDTH-1):0] mem [0: (1<<`SFIFO_ADDR_WIDTH)-1] ;
26
27 assign data_o = mem[rd_ptr[(`SFIFO_ADDR_WIDTH -1):0]] ;
28 always@( posedge clk_i) begin
29 if( por_i) begin
30 rd_ptr <= 0 ;
31 end
32 else if( re_i ) begin
33 if( ~empty_o) begin
34 rd_ptr <= rd_ptr + 1;
35 end
36 // synopsys translate_off
37 else begin
38 $display("Error : read on empty") ;
39 $stop ;
40 end // else
41 // synopsys translate_on
42 end // else if
43 end // always
44
45 always@( posedge clk_i) begin
46 if( por_i) begin
47 wr_ptr <= 0 ;
48 end
49 else if ( we_i ) begin
50 if( ~full_o) begin
51 mem[wr_ptr[(`SFIFO_ADDR_WIDTH -1):0]] <= data_i ;
52 wr_ptr <= wr_ptr + 1;
53 end
54 // synopsys translate_off
55 else begin
56 $display("Error : write on full ") ;
57 $stop ;
58 end // else
59 // synopsys translate_on
60 end // else if
61 end // always
62
63 assign empty_o = (wr_ptr == rd_ptr ) ? 1: 0 ;
64 assign full_o = (wr_ptr ==
65 {~rd_ptr[`SFIFO_ADDR_WIDTH ], rd_ptr[(`SFIFO_ADDR_WIDTH -1):0]} )
66 ? ~re_i : 0 ;
67
68 // synopsys translate_off
69 // debug purpose only
70 assign old_full = (wr_ptr ==
71 {~rd_ptr[`SFIFO_ADDR_WIDTH ], rd_ptr[(`SFIFO_ADDR_WIDTH -1):0]} )
72 ? 1 : 0 ;
73 assign both_full = re_i & we_i & old_full ;
74 // synopsys translate_on
75 endmodule // sfifo
76 // EOF sfifo.v