- UID
- 864567
|
我读书时候学过VHDL,那时候一门课学了好几种语言,还有一种是ABEL,另外一种连名字都忘了。当时ABEL学得最熟悉,因为最早开课,VHDL看起来太繁琐没学会多少。刚毕业那时候用过CPLD,但是那时是用画原理图的办法来开发的,处理复杂的时序逻辑比较困难。毕业四年后进了研究所,当时的有同事懂一点点Verilog,感觉语句跟C很像,我对这个也有了一点点兴趣,但是没去练,当时搞ARM跟学linux操作去了。去年我在淘宝买了一块特权同学的SF-EP1V2 FPGA学习板,想自己学习一下Verilog HDL语言,后来慢慢有时间才做了一些练习。
下面这个module是参考一个I2C的Verilog HDL写的,这个处理时序的方法跟自己以前写的真不一样。自己写的虽然功能也出来了,但是一大堆异步逻辑,总觉得不太妥当。这个时序逻辑的思想是用一个计数器来控制时序信号的输出,输出的状态由几个变量来控制。
module test595 (
CLOCK,
ds_shcp,//serial clock input
ds_stcp,// parallel clock input
ds_data,//parallel data
HC595_DATA,//DATA:[segment code, location code]
GO, //GO transfer
RESET
//TEST
//SD_COUNTER,
//SDO
);
input CLOCK;
input [15:0]HC595_DATA;
input GO;
input RESET;
output ds_data;
output ds_shcp;
output ds_stcp;
//TEST
//output [4:0] SD_COUNTER;
//output SDO;
reg SDO;
reg SCLK;
reg STO;
reg END;
reg [15:0]SD;
reg [4:0]SD_COUNTER;
wire ds_shcp=SCLK | ( ((SD_COUNTER >= 3) & (SD_COUNTER <=18))? ~CLOCK :0 );
wire ds_data=SDO?1'b1:0 ;
wire ds_stcp=STO | ((SD_COUNTER==19)?1'b1:1'b0);
//SHIFT COUNTER
always @(negedge RESET or posedge CLOCK ) begin
if (!RESET) SD_COUNTER=5'b11111;
else begin
if (GO==0)
SD_COUNTER=0;
else
if (SD_COUNTER < 5'b11111) SD_COUNTER=SD_COUNTER+1;
end
end
//----
always @(negedge RESET or posedge CLOCK ) begin
if (!RESET) begin SCLK=1;SDO=1;STO=1; end
else
case (SD_COUNTER)
5'd0 : begin SDO=1; SCLK=1;end
//start
5'd1 : begin SD=HC595_DATA;SDO=0;end
5'd2 : SCLK=0;
//SLAVE ADDR
5'd3 : SDO=SD[15];
5'd4 : SDO=SD[14];
5'd5 : SDO=SD[13];
5'd6 : SDO=SD[12];
5'd7 : SDO=SD[11];
5'd8 : SDO=SD[10];
5'd9 : SDO=SD[9];
5'd10 : SDO=SD[8];
6'd11 : SDO=SD[7];
//SUB ADDR
5'd12 : SDO=SD[6];
5'd13 : SDO=SD[5];
5'd14 : SDO=SD[4];
5'd15 : SDO=SD[3];
5'd16 : SDO=SD[2];
5'd17 : SDO=SD[1];
5'd18 : SDO=SD[0];
5'd19 : begin SCLK=1'b1; STO=1'b0; end
5'd20 : STO=1'b0;
5'd20 : STO=1'b1;
default:begin SCLK=1;SDO=1;STO=1; end
endcase
end
endmodule
下面是调用了该module的一个下载到开发板的模块,实现一个计数器并显示。可能语句又比较烂了,希望今后水平提高了能有所改进。
module seg7(clk1,rst_n,ds_shcp,ds_stcp,ds_data//,
//test
//code,GO,dis_code
);
input clk1;//25MHz
input rst_n;
output ds_shcp,ds_stcp,ds_data;
//output code;
//output GO;
//output dis_code;
wire dsdata;
assign ds_data=dsdata;
reg [15:0]code;//code to be display
reg GO;
reg [7:0]divd;
always @(posedge clk1 or negedge rst_n)
if(!rst_n) divd<=0;
else divd<=divd+1;
assign clk=divd[7];
//开发板用了25MHz的晶振,计数太快了,不得不分频一下,搞了个异步时钟
//count
reg [7:0]cnt;
always @(posedge clk or negedge rst_n)
if(!rst_n) cnt<=0;
else cnt<=cnt+1;
reg [7:0]cntcode;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin cntcode<=0;code<=0; end
else if(cnt==8'hff)
begin
cntcode<=cntcode+1;
if(cntcode==8'hff) code<=code+1;
end
end
//decode
parameter
data0=8'b00111111,//8'b11111100,//0
data1=8'b00000110,//8'b01100000,//1
data2=8'b01011011,//8'b11011010,//2
data3=8'b01001111,//8'b11110010,//3
data4=8'b01100110,//8'b01100110,//4
data5=8'b01101101,//8'b10110110,//5
data6=8'b01111101,//8'b10111110,//6
data7=8'b00000111,//8'b11100000,//7
data8=8'b01111111,//8'b11111110,//8
data9=8'b01101111,//8'b11110110,//9
dataa=8'b01110111,//8'b11101110,//a
datab=8'b01111100,//8'b00111110,//b
datac=8'b00111001,//8'b10011100,//c
datad=8'b01011110,//8'b01111010,//d
datae=8'b01111001,//8'b10011110,//e
dataf=8'b01110001;//8'b10001110;//f
reg[15:0] dis_code;
reg [11:0]decode;
always @(posedge clk or negedge rst_n)
if(!rst_n) GO=1;
else if(cnt>=8'h20 && cnt<=8'h24) begin decode={code[3:0],8'hf7};GO=0; end
else if(cnt>=8'h60 && cnt<=8'h64) begin decode={code[7:4],8'hfb};GO=0; end
else if(cnt>=8'ha0 && cnt<=8'ha4) begin decode={code[11:8],8'hfd};GO=0; end
else if(cnt>=8'he0 && cnt<=8'he4) begin decode={code[15:12],8'hfe};GO=0; end
else GO=1;
always @(posedge clk or negedge rst_n)
if(!rst_n) dis_code<=0;
else
case(decode[11:8])
4'h0:dis_code={data0,decode[7:0]};
4'h1:dis_code={data1,decode[7:0]};
4'h2:dis_code={data2,decode[7:0]};
4'h3:dis_code={data3,decode[7:0]};
4'h4:dis_code={data4,decode[7:0]};
4'h5:dis_code={data5,decode[7:0]};
4'h6:dis_code={data6,decode[7:0]};
4'h7:dis_code={data7,decode[7:0]};
4'h8:dis_code={data8,decode[7:0]};
4'h9:dis_code={data9,decode[7:0]};
4'ha:dis_code={dataa,decode[7:0]};
4'hb:dis_code={datab,decode[7:0]};
4'hc:dis_code={datac,decode[7:0]};
4'hd:dis_code={datad,decode[7:0]};
4'he:dis_code={datae,decode[7:0]};
4'hf:dis_code={dataf,decode[7:0]};
endcase
test595 HC595(
.CLOCK(cnt[0]),
.ds_shcp(ds_shcp),//serial clock input
.ds_stcp(ds_stcp),// paralet clock input
.ds_data(dsdata),//I2C DATA
.HC595_DATA(dis_code),//DATA:[SLAVE_ADDR,SUB_ADDR,DATA]
.GO(GO), //GO transfor
.RESET(rst_n)
//TEST
//SD_COUNTER,
//SDO
);
endmodule |
|