sim中do文件/memory(readmemb命令符)/移位編寫

此工程是並行數據的實驗

  1. do文件模板(自動仿真文件)
    Modelsim do 文件的自動化仿真
    1.1 建立庫
    1.2 映射庫到物理目錄
    1.3 編譯源文件
    1.4 啓動仿真器
    1.5 執行仿真

#此處是註釋
#退出當前仿真功能
quit -sim
#清楚命令行顯示信息
.main   clear
#建立一個lib庫
vlib  ./lib
#在lib中建立一個work
vlib  ./lib/work

#映射邏輯庫名,將邏輯庫名映射庫路徑中
vmap work  ./lib/work

#編譯指令  編譯源文件
vlog   -work  work   ./tb_ex_shift_reg.v
vlog   -work  work   ./../design/*.v        
# 以上爲編譯指令 */

#啓動仿真器
vsim   -voptargs=+acc  work.tb_ex_shift_reg

#-divider 分隔符
add wave        -divider  {tb_111}
# 添加觀察項
add  wave    tb_ex_shift_reg/lvds_d
add  wave    tb_ex_shift_reg/o_lvds_d
add  wave    tb_ex_shift_reg/i_30
add  wave    tb_ex_shift_reg/lvds_clock
add  wave    tb_ex_shift_reg/rst_n

# *號代表通配符
add wave        -divider  {ex_shift_reg_instaa}

add  wave    tb_ex_shift_reg/ex_shift_reg_inst/*

run  100us
  1. tb激勵文件
    注意:readmemb命令符的使用

`timescale     1ns/1ns  //單位時標聲明 1ns是單位
module tb_ex_shift_reg();
reg  lvds_clock;
reg  rst_n;
reg  [0:0]   mem1x16 [15:0];   //這是聲明memory變量,第一個[]是位寬,第二個[]是深度.
reg  lvds_d = 0;
wire [7:0]   o_lvds_d = 0;
reg  [3:0]   i_30;

initial begin
 lvds_clock = 0;
 rst_n = 0;
 #90
 rst_n = 1;
end

always #10 lvds_clock <= ~lvds_clock;
// 在根目錄中建立了data.txt文件
initial begin
  $readmemb ("./data.txt",mem1x16);    // readmemb命令符,這個最後b爲二進制,也可以是h(16進制) 
end 

ex_shift_reg  ex_shift_reg_inst(
  .lvds_clk   (lvds_clock),
  .rst_n      (rst_n),
  .lvds_d     (lvds_d),
  .o_lvds_d   (o_lvds_d)
 );

initial begin
  #100
  lvds_send_d();
end

task   lvds_send_d();
  integer  i;
  begin
   for (i=0; i<=255; i=i+1)
   begin
    @(posedge  lvds_clock);
    lvds_d <= mem1x16[i[3:0]];
                i_30 <= i[3:0];
   end
  end
endtask

endmodule

  1. tata.txt
    注意此文件是放在sim文件夾中
1
0
1
0
1
0
1
0
1
0
0
0
1
0
0
0
  1. 串轉並行數據的源文件
    注:lvds數據轉並行
module ex_shift_reg(
  input  wire   lvds_clk,
  input   wire        rst_n,
  input   wire        lvds_d,
  output  reg  [7:0]  o_lvds_d
};
reg  [7:0] shift_reg; // 用戶存儲我們的串轉並的數據;
reg     [2:0]   s_cnt;
reg             s_flag; 
reg             s_flag_dly1,s_flag_dly2,s_flag_dly3;

// 位拼接符{7'b1010_00,3'b010} ---> 10'b1010_000_010 等效的;
// 注意左移和右移的用法
always @(posedge lvds_clk or negedge rst_n) begin
 if (rst_n == 1'b0) begin
  shift_reg <= 'd0;
 end
 else begin
  //shift_reg <= {shift_reg[6:0],lvds_d};   // 左移
  shift_reg <= {lvds_d,shift_reg[7:1]};     // 右移
 end
end
// 第一個時鐘週期{0000_000lvds_d1}
// 第二個時鐘週期{0000_00lvds_d1 lvds_d2}
// .....
// 第八個時鐘週期{lvds_d1 d2 ... d8}
always @(posedge lvds_clk or negedge rst_n) begin
 if (rst_n == 1'b0) begin
   s_cnt <= 'd0;
 end
 else begin
  s_cnt <= s_cnt + 1'b1;
 end
end

always @(s_cnt) //()內爲敏感列表,如何寫全敏感列表,條件列表裏的所有變量,以及賦值語句右邊的所有變量
  if (s_cnt == 3'd7)
    s_flag <= 1'b1;
  else
    s_flag <= 1'b0; //這個分支條件一定要寫全,不然生產鎖存器,鎖存器在fpga中是很危險的

always @(posedge lvds_clk or posedge rst_n) begin
 if (rst_n == 1'b0) begin
  o_lvds_d <= 'd0;
 end
 else if (s_flag_dly3 == 1'b1) begin
  o_lvds_d <= shift_reg;
 end
end
// 延時打拍的用法
always @(posedge lvds_clk)
  {s_flag_dly3,s_flag_dly2,s_flag_dly1} <= {s_flag_dly2,s_flag_dly1,s_flag};

endmodule

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章