【随笔】“真OO无双”前辈提供的SEG7_Controller模块的问题改进
首先,非常感謝“真OO無雙”前輩,在學習FPGA過程中給與了極大幫助。在此記錄一些問題,希望能幫助別人,也給自己留點記錄,方便以后查找。
????? 前輩在(原創) 如何設計一個七段顯示器Controller? 中給了出了一個例子,如下:
我的板子是DE3—150,上面有兩顆數碼管。將其作為自定義組建加入到SOPC Builder中(具體參考(原創) 如何設計一個七段顯示器Controller? ),其參數修改為:
?
1 module SEG7_Controller (2 // Avalon clock interface siganals
3 ? input csi_clockreset_clk,
4 input csi_clockreset_reset_n,
5 // Signals for Avalon-MM slave port
6 ? input [ADDR_WIDTH-1:0] avs_s1_address,
7 input avs_s1_write,
8 input [DATA_WIDTH-1:0] avs_s1_writedata,
9 // user logic inputs and outputs
10 ? output [SEG7_NUM*8-1:0] avs_s1_export_oHEX
11 );
12
13 parameter DATA_WIDTH = 32; // data bus width
14 ?parameter SEG7_NUM = 8; // specify the number of seg7 unit
15 ?parameter ADDR_WIDTH = 3; // log2(SEG7_NUM)
16 ?
17 reg [SEG7_NUM-1:0] base_index;
18 reg [DATA_WIDTH-1:0] write_data;
19 reg [(SEG7_NUM*8-1):0] reg_file;
20
21 assign avs_s1_export_oHEX = ~reg_file;
22
23 always@(posedge csi_clockreset_clk, negedge csi_clockreset_reset_n) begin
24 if (!csi_clockreset_reset_n) begin
25 integer i;
26 base_index <= 8'h00;
27 write_data <= 8'h00;
28
29 for(i = 0; i < SEG7_NUM * 8; i = i + 1)
30 reg_file[i] <= 1'b1;
31 end
32 else begin
33 if (avs_s1_write) begin
34 integer j;
35 write_data <= avs_s1_writedata;
36 base_index <= (avs_s1_address << 3);
37
38 for(j = 0; j < 8; j = j + 1)
39 reg_file[base_index+j] <= write_data[j];
40 end
41 end
42 end
43
44 endmodule
?
?
?
SEG7_NUM = 2;ADDR_WIDTH = 1;
?
編譯下載到板子上,然后在Nios II中運行測試程序,在低位向高位進位時出現錯誤現象:
...08—>09—>00—>11—>12...19—>10—>21...
也就是說,低位向高位進位時,低位清零,高位沒變化,下一次更新時,高低位一起更新。
分析代碼33~39行,由于使用阻塞賦值,reg_file,base_index以及write_data中的數據其實都是前一時鐘周期的,那么其中數值變化如下:
?。
修改代碼如下,問題解決。
?
1 module SEG7_Controller (2 // Avalon clock interface siganals
3 input csi_clockreset_clk,
4 input csi_clockreset_reset_n,
5 // Signals for Avalon-MM slave port
6 input [ADDR_WIDTH-1:0] avs_s1_address,
7 input avs_s1_write,
8 input [31:0] avs_s1_writedata,
9 // user logic inputs and outputs
10 output [SEG7_NUM*8-1:0] avs_s1_export_oHEX
11 );
12
13 parameter SEG7_NUM = 8; // specify the number of seg7 unit
14 parameter ADDR_WIDTH = 3; // log2(SEG7_NUM)
15 parameter DEFAULT_ACTIVE = 1;
16 parameter LOW_ACTIVE = 1;
17
18 reg [(SEG7_NUM*8-1):0] reg_file;
19
20 assign avs_s1_export_oHEX = (LOW_ACTIVE)?~reg_file:reg_file;
21
22 always@(posedge csi_clockreset_clk, negedge csi_clockreset_reset_n) begin
23 if (!csi_clockreset_reset_n) begin
24 reg_file[(SEG7_NUM*8-1):0] <= (DEFAULT_ACTIVE)?8'hFF:8'h00; // trun on or off
25 end
26 else begin
27 if (avs_s1_write) begin
28 integer j;
29 for(j = 0; j < 8; j = j + 1)
30 reg_file[(avs_s1_address << 3) + j] <= avs_s1_writedata[j];
31 // reg_file[((avs_s1_address << 3) + 7 ):(avs_s1_address << 3)] <= avs_s1_writedata[7:0];
32 end
33 end
34 end
35
36 endmodule
?
?
方法二,還可以在起另外一個always塊,在其中完成write_data對reg_file的賦值,因為clk非常快,不受avs_s1_write信號控制,可以避免此情況。
?
總結:
- reg變量,相當于觸發器,若采用阻塞賦值,傳遞出去的其實是其存放的前一時鐘周期的值。
- 制作自定義組建時,對寄存器的讀寫,應該與寄存器功能實現分開,如方法2.?
?
?
?
?
?
?
?
?
?
轉載于:https://www.cnblogs.com/xiyi/archive/2010/11/03/1868427.html
總結
以上是生活随笔為你收集整理的【随笔】“真OO无双”前辈提供的SEG7_Controller模块的问题改进的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 幼儿绘本故事教案一等奖
- 下一篇: 迅捷 FW450R 无线路由器设置无线W